1 //===-- NativeRegisterContextLinux_arm64.cpp --------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #if defined (__arm64__) || defined (__aarch64__)
11 
12 #include "NativeRegisterContextLinux_arm64.h"
13 
14 // C Includes
15 // C++ Includes
16 
17 // Other libraries and framework includes
18 #include "lldb/Core/DataBufferHeap.h"
19 #include "lldb/Core/Error.h"
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/RegisterValue.h"
22 #include "lldb/Host/common/NativeProcessProtocol.h"
23 
24 #include "Plugins/Process/Linux/NativeProcessLinux.h"
25 #include "Plugins/Process/Linux/Procfs.h"
26 #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
27 
28 // System includes - They have to be included after framework includes because they define some
29 // macros which collide with variable names in other modules
30 #include <sys/socket.h>
31 // NT_PRSTATUS and NT_FPREGSET definition
32 #include <elf.h>
33 
34 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
35 
36 using namespace lldb;
37 using namespace lldb_private;
38 using namespace lldb_private::process_linux;
39 
40 // ARM64 general purpose registers.
41 static const uint32_t g_gpr_regnums_arm64[] =
42 {
43     gpr_x0_arm64,
44     gpr_x1_arm64,
45     gpr_x2_arm64,
46     gpr_x3_arm64,
47     gpr_x4_arm64,
48     gpr_x5_arm64,
49     gpr_x6_arm64,
50     gpr_x7_arm64,
51     gpr_x8_arm64,
52     gpr_x9_arm64,
53     gpr_x10_arm64,
54     gpr_x11_arm64,
55     gpr_x12_arm64,
56     gpr_x13_arm64,
57     gpr_x14_arm64,
58     gpr_x15_arm64,
59     gpr_x16_arm64,
60     gpr_x17_arm64,
61     gpr_x18_arm64,
62     gpr_x19_arm64,
63     gpr_x20_arm64,
64     gpr_x21_arm64,
65     gpr_x22_arm64,
66     gpr_x23_arm64,
67     gpr_x24_arm64,
68     gpr_x25_arm64,
69     gpr_x26_arm64,
70     gpr_x27_arm64,
71     gpr_x28_arm64,
72     gpr_fp_arm64,
73     gpr_lr_arm64,
74     gpr_sp_arm64,
75     gpr_pc_arm64,
76     gpr_cpsr_arm64,
77     LLDB_INVALID_REGNUM // register sets need to end with this flag
78 };
79 static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \
80               "g_gpr_regnums_arm64 has wrong number of register infos");
81 
82 // ARM64 floating point registers.
83 static const uint32_t g_fpu_regnums_arm64[] =
84 {
85     fpu_v0_arm64,
86     fpu_v1_arm64,
87     fpu_v2_arm64,
88     fpu_v3_arm64,
89     fpu_v4_arm64,
90     fpu_v5_arm64,
91     fpu_v6_arm64,
92     fpu_v7_arm64,
93     fpu_v8_arm64,
94     fpu_v9_arm64,
95     fpu_v10_arm64,
96     fpu_v11_arm64,
97     fpu_v12_arm64,
98     fpu_v13_arm64,
99     fpu_v14_arm64,
100     fpu_v15_arm64,
101     fpu_v16_arm64,
102     fpu_v17_arm64,
103     fpu_v18_arm64,
104     fpu_v19_arm64,
105     fpu_v20_arm64,
106     fpu_v21_arm64,
107     fpu_v22_arm64,
108     fpu_v23_arm64,
109     fpu_v24_arm64,
110     fpu_v25_arm64,
111     fpu_v26_arm64,
112     fpu_v27_arm64,
113     fpu_v28_arm64,
114     fpu_v29_arm64,
115     fpu_v30_arm64,
116     fpu_v31_arm64,
117     fpu_fpsr_arm64,
118     fpu_fpcr_arm64,
119     LLDB_INVALID_REGNUM // register sets need to end with this flag
120 };
121 static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \
122               "g_fpu_regnums_arm64 has wrong number of register infos");
123 
124 namespace {
125     // Number of register sets provided by this context.
126     enum
127     {
128         k_num_register_sets = 2
129     };
130 }
131 
132 // Register sets for ARM64.
133 static const RegisterSet
134 g_reg_sets_arm64[k_num_register_sets] =
135 {
136     { "General Purpose Registers",  "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 },
137     { "Floating Point Registers",   "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 }
138 };
139 
140 namespace
141 {
142 
143 class ReadRegOperation : public NativeProcessLinux::Operation
144 {
145 public:
146     ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, RegisterValue &value) :
147         m_tid(tid),
148         m_offset(static_cast<uintptr_t>(offset)),
149         m_reg_name(reg_name),
150         m_value(value)
151     { }
152 
153     void
154     Execute(NativeProcessLinux *monitor) override;
155 
156 private:
157     lldb::tid_t m_tid;
158     uintptr_t m_offset;
159     const char *m_reg_name;
160     RegisterValue &m_value;
161 };
162 
163 class WriteRegOperation : public NativeProcessLinux::Operation
164 {
165 public:
166     WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) :
167         m_tid(tid),
168         m_offset(offset),
169         m_reg_name(reg_name),
170         m_value(value)
171     { }
172 
173     void
174     Execute(NativeProcessLinux *monitor) override;
175 
176 private:
177     lldb::tid_t m_tid;
178     uintptr_t m_offset;
179     const char *m_reg_name;
180     const RegisterValue &m_value;
181 };
182 
183 class ReadGPROperation : public NativeProcessLinux::Operation
184 {
185 public:
186     ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size)
187         : m_tid(tid), m_buf(buf), m_buf_size(buf_size)
188         { }
189 
190     void Execute(NativeProcessLinux *monitor) override;
191 
192 private:
193     lldb::tid_t m_tid;
194     void *m_buf;
195     size_t m_buf_size;
196 };
197 
198 class WriteGPROperation : public NativeProcessLinux::Operation
199 {
200 public:
201     WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) :
202         m_tid(tid), m_buf(buf), m_buf_size(buf_size)
203     { }
204 
205     void Execute(NativeProcessLinux *monitor) override;
206 
207 private:
208     lldb::tid_t m_tid;
209     void *m_buf;
210     size_t m_buf_size;
211 };
212 
213 class ReadFPROperation : public NativeProcessLinux::Operation
214 {
215 public:
216     ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size)
217         : m_tid(tid),
218           m_buf(buf),
219           m_buf_size(buf_size)
220         { }
221 
222     void Execute(NativeProcessLinux *monitor) override;
223 
224 private:
225     lldb::tid_t m_tid;
226     void *m_buf;
227     size_t m_buf_size;
228 };
229 
230 class WriteFPROperation : public NativeProcessLinux::Operation
231 {
232 public:
233     WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size)
234         : m_tid(tid), m_buf(buf), m_buf_size(buf_size)
235         { }
236 
237     void Execute(NativeProcessLinux *monitor) override;
238 
239 private:
240     lldb::tid_t m_tid;
241     void *m_buf;
242     size_t m_buf_size;
243 };
244 
245 class ReadDBGROperation : public NativeProcessLinux::Operation
246 {
247 public:
248     ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp, unsigned int &count_bp)
249         : m_tid(tid),
250           m_count_wp(count_wp),
251           m_count_bp(count_bp)
252         { }
253 
254     void Execute(NativeProcessLinux *monitor) override;
255 
256 private:
257     lldb::tid_t m_tid;
258     unsigned int &m_count_wp;
259     unsigned int &m_count_bp;
260 };
261 
262 class WriteDBGROperation : public NativeProcessLinux::Operation
263 {
264 public:
265     WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf,
266                        uint32_t *cntrl_buf, int type, int count)
267         : m_tid(tid),
268           m_address(addr_buf),
269           m_control(cntrl_buf),
270           m_type(type),
271           m_count(count)
272         { }
273 
274     void Execute(NativeProcessLinux *monitor) override;
275 
276 private:
277     lldb::tid_t m_tid;
278     lldb::addr_t * m_address;
279     uint32_t * m_control;
280     int m_type;
281     int m_count;
282 };
283 
284 } // end of anonymous namespace
285 
286 void
287 ReadRegOperation::Execute(NativeProcessLinux *monitor)
288 {
289     if (m_offset > sizeof(struct user_pt_regs))
290     {
291         uintptr_t offset = m_offset - sizeof(struct user_pt_regs);
292         if (offset > sizeof(struct user_fpsimd_state))
293         {
294             m_error.SetErrorString("invalid offset value");
295             return;
296         }
297         elf_fpregset_t regs;
298         int regset = NT_FPREGSET;
299         struct iovec ioVec;
300 
301         ioVec.iov_base = &regs;
302         ioVec.iov_len = sizeof regs;
303         NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
304         if (m_error.Success())
305         {
306             ArchSpec arch;
307             if (monitor->GetArchitecture(arch))
308                 m_value.SetBytes((void *)(((unsigned char *)(&regs)) + offset), 16, arch.GetByteOrder());
309             else
310                 m_error.SetErrorString("failed to get architecture");
311         }
312     }
313     else
314     {
315         elf_gregset_t regs;
316         int regset = NT_PRSTATUS;
317         struct iovec ioVec;
318 
319         ioVec.iov_base = &regs;
320         ioVec.iov_len = sizeof regs;
321         NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
322         if (m_error.Success())
323         {
324             ArchSpec arch;
325             if (monitor->GetArchitecture(arch))
326                 m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder());
327             else
328                 m_error.SetErrorString("failed to get architecture");
329         }
330     }
331 }
332 
333 void
334 WriteRegOperation::Execute(NativeProcessLinux *monitor)
335 {
336     if (m_offset > sizeof(struct user_pt_regs))
337     {
338         uintptr_t offset = m_offset - sizeof(struct user_pt_regs);
339         if (offset > sizeof(struct user_fpsimd_state))
340         {
341             m_error.SetErrorString("invalid offset value");
342             return;
343         }
344         elf_fpregset_t regs;
345         int regset = NT_FPREGSET;
346         struct iovec ioVec;
347 
348         ioVec.iov_base = &regs;
349         ioVec.iov_len = sizeof regs;
350         NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
351         if (m_error.Success())
352         {
353             ::memcpy((void *)(((unsigned char *)(&regs)) + offset), m_value.GetBytes(), 16);
354             NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
355         }
356     }
357     else
358     {
359         elf_gregset_t regs;
360         int regset = NT_PRSTATUS;
361         struct iovec ioVec;
362 
363         ioVec.iov_base = &regs;
364         ioVec.iov_len = sizeof regs;
365         NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
366         if (m_error.Success())
367         {
368             ::memcpy((void *)(((unsigned char *)(&regs)) + m_offset), m_value.GetBytes(), 8);
369             NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
370         }
371     }
372 }
373 
374 void
375 ReadGPROperation::Execute(NativeProcessLinux *monitor)
376 {
377     int regset = NT_PRSTATUS;
378     struct iovec ioVec;
379 
380     ioVec.iov_base = m_buf;
381     ioVec.iov_len = m_buf_size;
382     NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, m_buf_size, m_error);
383 }
384 
385 void
386 WriteGPROperation::Execute(NativeProcessLinux *monitor)
387 {
388     int regset = NT_PRSTATUS;
389     struct iovec ioVec;
390 
391     ioVec.iov_base = m_buf;
392     ioVec.iov_len = m_buf_size;
393     NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &regset, &ioVec, m_buf_size, m_error);
394 }
395 
396 void
397 ReadFPROperation::Execute(NativeProcessLinux *monitor)
398 {
399     int regset = NT_FPREGSET;
400     struct iovec ioVec;
401 
402     ioVec.iov_base = m_buf;
403     ioVec.iov_len = m_buf_size;
404     NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, m_buf_size, m_error);
405 }
406 
407 void
408 WriteFPROperation::Execute(NativeProcessLinux *monitor)
409 {
410     int regset = NT_FPREGSET;
411     struct iovec ioVec;
412 
413     ioVec.iov_base = m_buf;
414     ioVec.iov_len = m_buf_size;
415     NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &regset, &ioVec, m_buf_size, m_error);
416 }
417 
418 void
419 ReadDBGROperation::Execute(NativeProcessLinux *monitor)
420 {
421    int regset = NT_ARM_HW_WATCH;
422    struct iovec ioVec;
423    struct user_hwdebug_state dreg_state;
424 
425    ioVec.iov_base = &dreg_state;
426    ioVec.iov_len = sizeof (dreg_state);
427 
428    NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, ioVec.iov_len, m_error);
429 
430    m_count_wp = dreg_state.dbg_info & 0xff;
431    regset = NT_ARM_HW_BREAK;
432 
433    NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, &regset, &ioVec, ioVec.iov_len, m_error);
434    m_count_bp = dreg_state.dbg_info & 0xff;
435 }
436 
437 void
438 WriteDBGROperation::Execute(NativeProcessLinux *monitor)
439 {
440     struct iovec ioVec;
441     struct user_hwdebug_state dreg_state;
442 
443     memset (&dreg_state, 0, sizeof (dreg_state));
444     ioVec.iov_base = &dreg_state;
445     ioVec.iov_len = sizeof (dreg_state);
446 
447     if (m_type == 0)
448         m_type = NT_ARM_HW_WATCH;
449     else
450         m_type = NT_ARM_HW_BREAK;
451 
452     for (int i = 0; i < m_count; i++)
453     {
454         dreg_state.dbg_regs[i].addr = m_address[i];
455         dreg_state.dbg_regs[i].ctrl = m_control[i];
456     }
457 
458     NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error);
459 }
460 
461 NativeRegisterContextLinux*
462 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
463                                                                  NativeThreadProtocol &native_thread,
464                                                                  uint32_t concrete_frame_idx)
465 {
466     return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx);
467 }
468 
469 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
470                                                                     NativeThreadProtocol &native_thread,
471                                                                     uint32_t concrete_frame_idx) :
472     NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch))
473 {
474     switch (target_arch.GetMachine())
475     {
476         case llvm::Triple::aarch64:
477             m_reg_info.num_registers     = k_num_registers_arm64;
478             m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64;
479             m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64;
480             m_reg_info.last_gpr          = k_last_gpr_arm64;
481             m_reg_info.first_fpr         = k_first_fpr_arm64;
482             m_reg_info.last_fpr          = k_last_fpr_arm64;
483             m_reg_info.first_fpr_v       = fpu_v0_arm64;
484             m_reg_info.last_fpr_v        = fpu_v31_arm64;
485             m_reg_info.gpr_flags         = gpr_cpsr_arm64;
486             break;
487         default:
488             assert(false && "Unhandled target architecture.");
489             break;
490     }
491 
492     ::memset(&m_fpr, 0, sizeof (m_fpr));
493     ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64));
494     ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs));
495 
496     // 16 is just a maximum value, query hardware for actual watchpoint count
497     m_max_hwp_supported = 16;
498     m_max_hbp_supported = 16;
499     m_refresh_hwdebug_info = true;
500 }
501 
502 uint32_t
503 NativeRegisterContextLinux_arm64::GetRegisterSetCount () const
504 {
505     return k_num_register_sets;
506 }
507 
508 const RegisterSet *
509 NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const
510 {
511     if (set_index < k_num_register_sets)
512         return &g_reg_sets_arm64[set_index];
513 
514     return nullptr;
515 }
516 
517 Error
518 NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
519 {
520     Error error;
521 
522     if (!reg_info)
523     {
524         error.SetErrorString ("reg_info NULL");
525         return error;
526     }
527 
528     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
529 
530     if (IsFPR(reg))
531     {
532         error = ReadFPR();
533         if (error.Fail())
534             return error;
535     }
536     else
537     {
538         uint32_t full_reg = reg;
539         bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
540 
541         if (is_subreg)
542         {
543             // Read the full aligned 64-bit register.
544             full_reg = reg_info->invalidate_regs[0];
545         }
546 
547         error = ReadRegisterRaw(full_reg, reg_value);
548 
549         if (error.Success ())
550         {
551             // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
552             if (is_subreg && (reg_info->byte_offset & 0x1))
553                 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
554 
555             // If our return byte size was greater than the return value reg size, then
556             // use the type specified by reg_info rather than the uint64_t default
557             if (reg_value.GetByteSize() > reg_info->byte_size)
558                 reg_value.SetType(reg_info);
559         }
560         return error;
561     }
562 
563     // Get pointer to m_fpr variable and set the data from it.
564     assert (reg_info->byte_offset < sizeof m_fpr);
565     uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
566     switch (reg_info->byte_size)
567     {
568         case 2:
569             reg_value.SetUInt16(*(uint16_t *)src);
570             break;
571         case 4:
572             reg_value.SetUInt32(*(uint32_t *)src);
573             break;
574         case 8:
575             reg_value.SetUInt64(*(uint64_t *)src);
576             break;
577         default:
578             assert(false && "Unhandled data size.");
579             error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
580             break;
581     }
582 
583     return error;
584 }
585 
586 Error
587 NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
588 {
589     if (!reg_info)
590         return Error ("reg_info NULL");
591 
592     const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
593     if (reg_index == LLDB_INVALID_REGNUM)
594         return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
595 
596     if (IsGPR(reg_index))
597         return WriteRegisterRaw(reg_index, reg_value);
598 
599     if (IsFPR(reg_index))
600     {
601         // Get pointer to m_fpr variable and set the data to it.
602         assert (reg_info->byte_offset < sizeof(m_fpr));
603         uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
604         switch (reg_info->byte_size)
605         {
606             case 2:
607                 *(uint16_t *)dst = reg_value.GetAsUInt16();
608                 break;
609             case 4:
610                 *(uint32_t *)dst = reg_value.GetAsUInt32();
611                 break;
612             case 8:
613                 *(uint64_t *)dst = reg_value.GetAsUInt64();
614                 break;
615             default:
616                 assert(false && "Unhandled data size.");
617                 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
618         }
619 
620         Error error = WriteFPR();
621         if (error.Fail())
622             return error;
623 
624         return Error ();
625     }
626 
627     return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
628 }
629 
630 Error
631 NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
632 {
633     Error error;
634 
635     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
636     if (!data_sp)
637         return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
638 
639     error = ReadGPR();
640     if (error.Fail())
641         return error;
642 
643     error = ReadFPR();
644     if (error.Fail())
645         return error;
646 
647     uint8_t *dst = data_sp->GetBytes ();
648     if (dst == nullptr)
649     {
650         error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE);
651         return error;
652     }
653 
654     ::memcpy (dst, &m_gpr_arm64, GetGPRSize());
655     dst += GetGPRSize();
656     ::memcpy (dst, &m_fpr, sizeof(m_fpr));
657 
658     return error;
659 }
660 
661 Error
662 NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
663 {
664     Error error;
665 
666     if (!data_sp)
667     {
668         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
669         return error;
670     }
671 
672     if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
673     {
674         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ());
675         return error;
676     }
677 
678 
679     uint8_t *src = data_sp->GetBytes ();
680     if (src == nullptr)
681     {
682         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
683         return error;
684     }
685     ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ());
686 
687     error = WriteGPR();
688     if (error.Fail())
689         return error;
690 
691     src += GetRegisterInfoInterface ().GetGPRSize ();
692     ::memcpy (&m_fpr, src, sizeof(m_fpr));
693 
694     error = WriteFPR();
695     if (error.Fail())
696         return error;
697 
698     return error;
699 }
700 
701 bool
702 NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const
703 {
704     return reg <= m_reg_info.last_gpr;   // GPR's come first.
705 }
706 
707 bool
708 NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const
709 {
710     return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
711 }
712 
713 uint32_t
714 NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
715 {
716     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
717 
718     if (log)
719         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
720 
721     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
722     if (!process_sp)
723         return false;
724 
725     // Check if our hardware breakpoint and watchpoint information is updated.
726     if (m_refresh_hwdebug_info)
727     {
728         ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported);
729         m_refresh_hwdebug_info = false;
730     }
731 
732     uint32_t control_value, bp_index;
733 
734     // Check if size has a valid hardware breakpoint length.
735     if (size != 4)
736         return LLDB_INVALID_INDEX32;  // Invalid size for a AArch64 hardware breakpoint
737 
738     // Check 4-byte alignment for hardware breakpoint target address.
739     if (addr & 0x03)
740         return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned.
741 
742     // Setup control value
743     control_value = 0;
744     control_value |= ((1 << size) - 1) << 5;
745     control_value |= (2 << 1) | 1;
746 
747     // Iterate over stored hardware breakpoints
748     // Find a free bp_index or update reference count if duplicate.
749     bp_index = LLDB_INVALID_INDEX32;
750     for (uint32_t i = 0; i < m_max_hbp_supported; i++)
751     {
752         if ((m_hbr_regs[i].control & 1) == 0)
753         {
754             bp_index = i;  // Mark last free slot
755         }
756         else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value)
757         {
758             bp_index = i;  // Mark duplicate index
759             break;  // Stop searching here
760         }
761     }
762 
763      if (bp_index == LLDB_INVALID_INDEX32)
764         return LLDB_INVALID_INDEX32;
765 
766     // Add new or update existing watchpoint
767     if ((m_hbr_regs[bp_index].control & 1) == 0)
768     {
769         m_hbr_regs[bp_index].address = addr;
770         m_hbr_regs[bp_index].control = control_value;
771         m_hbr_regs[bp_index].refcount = 1;
772 
773         //TODO: PTRACE CALL HERE for an UPDATE
774     }
775     else
776         m_hbr_regs[bp_index].refcount++;
777 
778     return bp_index;
779 }
780 
781 bool
782 NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx)
783 {
784     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
785 
786     if (log)
787         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
788 
789     if (hw_idx >= m_max_hbp_supported)
790         return false;
791 
792     // Update reference count if multiple references.
793     if (m_hbr_regs[hw_idx].refcount > 1)
794     {
795         m_hbr_regs[hw_idx].refcount--;
796         return true;
797     }
798     else if (m_hbr_regs[hw_idx].refcount == 1)
799     {
800         m_hbr_regs[hw_idx].control &= ~1;
801         m_hbr_regs[hw_idx].address = 0;
802         m_hbr_regs[hw_idx].refcount = 0;
803 
804         //TODO: PTRACE CALL HERE for an UPDATE
805         return true;
806     }
807 
808     return false;
809 }
810 
811 uint32_t
812 NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints ()
813 {
814     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
815 
816     if (log)
817         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
818 
819     return m_max_hwp_supported;
820 }
821 
822 uint32_t
823 NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags)
824 {
825     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
826 
827     if (log)
828         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
829 
830     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
831     if (!process_sp)
832         return false;
833 
834 
835     // Check if our hardware breakpoint and watchpoint information is updated.
836     if (m_refresh_hwdebug_info)
837     {
838         ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported);
839         m_refresh_hwdebug_info = false;
840     }
841 
842     uint32_t control_value, wp_index;
843 
844 
845     if (watch_flags != 0x1 && watch_flags != 0x2 && watch_flags != 0x3)
846         return 0;//Error ("Invalid read/write bits for watchpoint");
847 
848     // Check if size has a valid hardware watchpoint length.
849     if (size != 1 && size != 2 && size != 4 && size != 8)
850         return 0;//Error ("Invalid size for watchpoint");
851 
852     // Check 8-byte alignment for hardware watchpoint target address.
853     // TODO: Add support for watching un-aligned addresses
854     if (addr & 0x07)
855         return 0;//Error ("LLDB for AArch64 currently supports 8-byte alignment for hardware watchpoint target address.");
856 
857     // Setup control value
858     control_value = watch_flags << 3;
859     control_value |= ((1 << size) - 1) << 5;
860     control_value |= (2 << 1) | 1;
861 
862     // Iterate over stored watchpoints
863     // Find a free wp_index or update reference count if duplicate.
864     wp_index = LLDB_INVALID_INDEX32;
865     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
866     {
867         if ((m_hwp_regs[i].control & 1) == 0)
868         {
869             wp_index = i; // Mark last free slot
870         }
871         else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value)
872         {
873             wp_index = i; // Mark duplicate index
874             break; // Stop searching here
875         }
876     }
877 
878      if (wp_index == LLDB_INVALID_INDEX32)
879         return LLDB_INVALID_INDEX32;
880 
881     // Add new or update existing watchpoint
882     if ((m_hwp_regs[wp_index].control & 1) == 0)
883     {
884         m_hwp_regs[wp_index].address = addr;
885         m_hwp_regs[wp_index].control = control_value;
886         m_hwp_regs[wp_index].refcount = 1;
887 
888         // PTRACE call to set corresponding watchpoint register.
889         WriteHardwareDebugRegs(&addr, &control_value, 0, wp_index);
890     }
891     else
892         m_hwp_regs[wp_index].refcount++;
893 
894     return wp_index;
895 }
896 
897 bool
898 NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index)
899 {
900     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
901 
902     if (log)
903         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
904 
905     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
906     if (!process_sp)
907         return false;
908 
909     if (wp_index >= m_max_hwp_supported)
910         return false;
911 
912     // Update reference count if multiple references.
913     if (m_hwp_regs[wp_index].refcount > 1)
914     {
915         m_hwp_regs[wp_index].refcount--;
916         return true;
917     }
918     else if (m_hwp_regs[wp_index].refcount == 1)
919     {
920         m_hwp_regs[wp_index].control &= ~1;
921         m_hwp_regs[wp_index].address = 0;
922         m_hwp_regs[wp_index].refcount = 0;
923 
924         //TODO: PTRACE CALL HERE for an UPDATE
925         WriteHardwareDebugRegs(&m_hwp_regs[wp_index].address, &m_hwp_regs[wp_index].control, 0, wp_index);
926         return true;
927     }
928 
929     return false;
930 }
931 
932 Error
933 NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints ()
934 {
935     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
936 
937     if (log)
938         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
939 
940     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
941 
942     Error ml_error;
943     ml_error.SetErrorToErrno();
944     if (!process_sp)
945         return ml_error;
946 
947     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
948     {
949         if (m_hwp_regs[i].control & 0x01)
950         {
951             m_hwp_regs[i].control &= ~1;
952             m_hwp_regs[i].address = 0;
953             m_hwp_regs[i].refcount = 0;
954 
955             WriteHardwareDebugRegs(&m_hwp_regs[i].address, &m_hwp_regs[i].control, 0, i);
956         }
957     }
958 
959     return Error();
960 }
961 
962 uint32_t
963 NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index)
964 {
965     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
966 
967     if (log)
968         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
969     switch ((m_hwp_regs[wp_index].control >> 5) & 0xff)
970     {
971         case 0x01:
972             return 1;
973         case 0x03:
974             return 2;
975         case 0x0f:
976             return 4;
977         case 0xff:
978             return 8;
979         default:
980             return 0;
981     }
982 }
983 bool
984 NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index)
985 {
986     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
987 
988     if (log)
989         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
990 
991     if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
992         return true;
993     else
994         return false;
995 }
996 
997 Error
998 NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
999 {
1000     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
1001 
1002     if (log)
1003         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
1004 
1005     uint32_t watch_size;
1006     lldb::addr_t watch_addr;
1007 
1008     for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
1009     {
1010         watch_size = GetWatchpointSize (wp_index);
1011         watch_addr = m_hwp_regs[wp_index].address;
1012 
1013         if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
1014             && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
1015         {
1016             return Error();
1017         }
1018     }
1019 
1020     wp_index = LLDB_INVALID_INDEX32;
1021     return Error();
1022 }
1023 
1024 lldb::addr_t
1025 NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index)
1026 {
1027     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
1028 
1029     if (log)
1030         log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
1031 
1032     if (wp_index >= m_max_hwp_supported)
1033         return LLDB_INVALID_ADDRESS;
1034 
1035     if (WatchpointIsEnabled(wp_index))
1036         return m_hwp_regs[wp_index].address;
1037     else
1038         return LLDB_INVALID_ADDRESS;
1039 }
1040 
1041 Error
1042 NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo(unsigned int &watch_count,
1043                                                         unsigned int &break_count)
1044 {
1045     NativeProcessProtocolSP process_sp (m_thread.GetProcess());
1046     if (!process_sp)
1047         return Error("NativeProcessProtocol is NULL");
1048     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
1049 
1050     ReadDBGROperation op(m_thread.GetID(), watch_count, break_count);
1051     return process_p->DoOperation(&op);
1052 }
1053 
1054 Error
1055 NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(lldb::addr_t *addr_buf,
1056                                                          uint32_t *cntrl_buf,
1057                                                          int type,
1058                                                          int count)
1059 {
1060     NativeProcessProtocolSP process_sp (m_thread.GetProcess());
1061     if (!process_sp)
1062         return Error("NativeProcessProtocol is NULL");
1063     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
1064 
1065     WriteDBGROperation op(m_thread.GetID(), addr_buf, cntrl_buf, type, count);
1066     return process_p->DoOperation(&op);
1067 }
1068 
1069 NativeProcessLinux::OperationUP
1070 NativeRegisterContextLinux_arm64::GetReadRegisterValueOperation(uint32_t offset,
1071                                                                 const char* reg_name,
1072                                                                 uint32_t size,
1073                                                                 RegisterValue &value)
1074 {
1075     return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value));
1076 }
1077 
1078 NativeProcessLinux::OperationUP
1079 NativeRegisterContextLinux_arm64::GetWriteRegisterValueOperation(uint32_t offset,
1080                                                                  const char* reg_name,
1081                                                                  const RegisterValue &value)
1082 {
1083     return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value));
1084 }
1085 
1086 NativeProcessLinux::OperationUP
1087 NativeRegisterContextLinux_arm64::GetReadGPROperation(void *buf, size_t buf_size)
1088 {
1089     return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size));
1090 }
1091 
1092 NativeProcessLinux::OperationUP
1093 NativeRegisterContextLinux_arm64::GetWriteGPROperation(void *buf, size_t buf_size)
1094 {
1095     return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size));
1096 }
1097 
1098 NativeProcessLinux::OperationUP
1099 NativeRegisterContextLinux_arm64::GetReadFPROperation(void *buf, size_t buf_size)
1100 {
1101     return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size));
1102 }
1103 
1104 NativeProcessLinux::OperationUP
1105 NativeRegisterContextLinux_arm64::GetWriteFPROperation(void *buf, size_t buf_size)
1106 {
1107     return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size));
1108 }
1109 
1110 #endif // defined (__arm64__) || defined (__aarch64__)
1111