1 //===-- NativeRegisterContextLinux_arm.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(__arm__)
11 
12 #include "NativeRegisterContextLinux_arm.h"
13 
14 #include "lldb/Core/DataBufferHeap.h"
15 #include "lldb/Core/Error.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/RegisterValue.h"
18 
19 #include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
20 
21 #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
22 
23 #ifndef PTRACE_GETVFPREGS
24   #define PTRACE_GETVFPREGS 27
25   #define PTRACE_SETVFPREGS 28
26 #endif
27 #ifndef PTRACE_GETHBPREGS
28   #define PTRACE_GETHBPREGS 29
29   #define PTRACE_SETHBPREGS 30
30 #endif
31 #if !defined(PTRACE_TYPE_ARG3)
32   #define PTRACE_TYPE_ARG3 void *
33 #endif
34 #if !defined(PTRACE_TYPE_ARG4)
35   #define PTRACE_TYPE_ARG4 void *
36 #endif
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 using namespace lldb_private::process_linux;
41 
42 // arm general purpose registers.
43 static const uint32_t g_gpr_regnums_arm[] =
44 {
45     gpr_r0_arm,
46     gpr_r1_arm,
47     gpr_r2_arm,
48     gpr_r3_arm,
49     gpr_r4_arm,
50     gpr_r5_arm,
51     gpr_r6_arm,
52     gpr_r7_arm,
53     gpr_r8_arm,
54     gpr_r9_arm,
55     gpr_r10_arm,
56     gpr_r11_arm,
57     gpr_r12_arm,
58     gpr_sp_arm,
59     gpr_lr_arm,
60     gpr_pc_arm,
61     gpr_cpsr_arm,
62     LLDB_INVALID_REGNUM // register sets need to end with this flag
63 };
64 static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \
65               "g_gpr_regnums_arm has wrong number of register infos");
66 
67 // arm floating point registers.
68 static const uint32_t g_fpu_regnums_arm[] =
69 {
70     fpu_s0_arm,
71     fpu_s1_arm,
72     fpu_s2_arm,
73     fpu_s3_arm,
74     fpu_s4_arm,
75     fpu_s5_arm,
76     fpu_s6_arm,
77     fpu_s7_arm,
78     fpu_s8_arm,
79     fpu_s9_arm,
80     fpu_s10_arm,
81     fpu_s11_arm,
82     fpu_s12_arm,
83     fpu_s13_arm,
84     fpu_s14_arm,
85     fpu_s15_arm,
86     fpu_s16_arm,
87     fpu_s17_arm,
88     fpu_s18_arm,
89     fpu_s19_arm,
90     fpu_s20_arm,
91     fpu_s21_arm,
92     fpu_s22_arm,
93     fpu_s23_arm,
94     fpu_s24_arm,
95     fpu_s25_arm,
96     fpu_s26_arm,
97     fpu_s27_arm,
98     fpu_s28_arm,
99     fpu_s29_arm,
100     fpu_s30_arm,
101     fpu_s31_arm,
102     fpu_fpscr_arm,
103     LLDB_INVALID_REGNUM // register sets need to end with this flag
104 };
105 static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \
106               "g_fpu_regnums_arm has wrong number of register infos");
107 
108 namespace {
109     // Number of register sets provided by this context.
110     enum
111     {
112         k_num_register_sets = 2
113     };
114 }
115 
116 // Register sets for arm.
117 static const RegisterSet
118 g_reg_sets_arm[k_num_register_sets] =
119 {
120     { "General Purpose Registers",  "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm },
121     { "Floating Point Registers",   "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
122 };
123 
124 NativeRegisterContextLinux*
125 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
126                                                                  NativeThreadProtocol &native_thread,
127                                                                  uint32_t concrete_frame_idx)
128 {
129     return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
130 }
131 
132 NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
133                                                                 NativeThreadProtocol &native_thread,
134                                                                 uint32_t concrete_frame_idx) :
135     NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm(target_arch))
136 {
137     switch (target_arch.GetMachine())
138     {
139         case llvm::Triple::arm:
140             m_reg_info.num_registers     = k_num_registers_arm;
141             m_reg_info.num_gpr_registers = k_num_gpr_registers_arm;
142             m_reg_info.num_fpr_registers = k_num_fpr_registers_arm;
143             m_reg_info.last_gpr          = k_last_gpr_arm;
144             m_reg_info.first_fpr         = k_first_fpr_arm;
145             m_reg_info.last_fpr          = k_last_fpr_arm;
146             m_reg_info.first_fpr_v       = fpu_s0_arm;
147             m_reg_info.last_fpr_v        = fpu_s31_arm;
148             m_reg_info.gpr_flags         = gpr_cpsr_arm;
149             break;
150         default:
151             assert(false && "Unhandled target architecture.");
152             break;
153     }
154 
155     ::memset(&m_fpr, 0, sizeof (m_fpr));
156     ::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm));
157     ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs));
158 
159     // 16 is just a maximum value, query hardware for actual watchpoint count
160     m_max_hwp_supported = 16;
161     m_max_hbp_supported = 16;
162     m_refresh_hwdebug_info = true;
163 }
164 
165 uint32_t
166 NativeRegisterContextLinux_arm::GetRegisterSetCount () const
167 {
168     return k_num_register_sets;
169 }
170 
171 uint32_t
172 NativeRegisterContextLinux_arm::GetUserRegisterCount() const
173 {
174     uint32_t count = 0;
175     for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
176         count += g_reg_sets_arm[set_index].num_registers;
177     return count;
178 }
179 
180 const RegisterSet *
181 NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const
182 {
183     if (set_index < k_num_register_sets)
184         return &g_reg_sets_arm[set_index];
185 
186     return nullptr;
187 }
188 
189 Error
190 NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
191 {
192     Error error;
193 
194     if (!reg_info)
195     {
196         error.SetErrorString ("reg_info NULL");
197         return error;
198     }
199 
200     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
201 
202     if (IsFPR(reg))
203     {
204         error = ReadFPR();
205         if (error.Fail())
206             return error;
207     }
208     else
209     {
210         uint32_t full_reg = reg;
211         bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
212 
213         if (is_subreg)
214         {
215             // Read the full aligned 64-bit register.
216             full_reg = reg_info->invalidate_regs[0];
217         }
218 
219         error = ReadRegisterRaw(full_reg, reg_value);
220 
221         if (error.Success ())
222         {
223             // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
224             if (is_subreg && (reg_info->byte_offset & 0x1))
225                 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
226 
227             // If our return byte size was greater than the return value reg size, then
228             // use the type specified by reg_info rather than the uint64_t default
229             if (reg_value.GetByteSize() > reg_info->byte_size)
230                 reg_value.SetType(reg_info);
231         }
232         return error;
233     }
234 
235     // Get pointer to m_fpr variable and set the data from it.
236     uint32_t fpr_offset = CalculateFprOffset(reg_info);
237     assert (fpr_offset < sizeof m_fpr);
238     uint8_t *src = (uint8_t *)&m_fpr + fpr_offset;
239     switch (reg_info->byte_size)
240     {
241         case 2:
242             reg_value.SetUInt16(*(uint16_t *)src);
243             break;
244         case 4:
245             reg_value.SetUInt32(*(uint32_t *)src);
246             break;
247         case 8:
248             reg_value.SetUInt64(*(uint64_t *)src);
249             break;
250         default:
251             assert(false && "Unhandled data size.");
252             error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
253             break;
254     }
255 
256     return error;
257 }
258 
259 Error
260 NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
261 {
262     if (!reg_info)
263         return Error ("reg_info NULL");
264 
265     const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
266     if (reg_index == LLDB_INVALID_REGNUM)
267         return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
268 
269     if (IsGPR(reg_index))
270         return WriteRegisterRaw(reg_index, reg_value);
271 
272     if (IsFPR(reg_index))
273     {
274         // Get pointer to m_fpr variable and set the data to it.
275         uint32_t fpr_offset = CalculateFprOffset(reg_info);
276         assert (fpr_offset < sizeof m_fpr);
277         uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset;
278         switch (reg_info->byte_size)
279         {
280             case 2:
281                 *(uint16_t *)dst = reg_value.GetAsUInt16();
282                 break;
283             case 4:
284                 *(uint32_t *)dst = reg_value.GetAsUInt32();
285                 break;
286             case 8:
287                 *(uint64_t *)dst = reg_value.GetAsUInt64();
288                 break;
289             default:
290                 assert(false && "Unhandled data size.");
291                 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
292         }
293 
294         Error error = WriteFPR();
295         if (error.Fail())
296             return error;
297 
298         return Error ();
299     }
300 
301     return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
302 }
303 
304 Error
305 NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
306 {
307     Error error;
308 
309     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
310     if (!data_sp)
311         return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE);
312 
313     error = ReadGPR();
314     if (error.Fail())
315         return error;
316 
317     error = ReadFPR();
318     if (error.Fail())
319         return error;
320 
321     uint8_t *dst = data_sp->GetBytes ();
322     if (dst == nullptr)
323     {
324         error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE);
325         return error;
326     }
327 
328     ::memcpy (dst, &m_gpr_arm, GetGPRSize());
329     dst += GetGPRSize();
330     ::memcpy (dst, &m_fpr, sizeof(m_fpr));
331 
332     return error;
333 }
334 
335 Error
336 NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
337 {
338     Error error;
339 
340     if (!data_sp)
341     {
342         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
343         return error;
344     }
345 
346     if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
347     {
348         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize ());
349         return error;
350     }
351 
352 
353     uint8_t *src = data_sp->GetBytes ();
354     if (src == nullptr)
355     {
356         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
357         return error;
358     }
359     ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ());
360 
361     error = WriteGPR();
362     if (error.Fail())
363         return error;
364 
365     src += GetRegisterInfoInterface ().GetGPRSize ();
366     ::memcpy (&m_fpr, src, sizeof(m_fpr));
367 
368     error = WriteFPR();
369     if (error.Fail())
370         return error;
371 
372     return error;
373 }
374 
375 bool
376 NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const
377 {
378     return reg <= m_reg_info.last_gpr;   // GPR's come first.
379 }
380 
381 bool
382 NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const
383 {
384     return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
385 }
386 
387 uint32_t
388 NativeRegisterContextLinux_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
389 {
390     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
391 
392     if (log)
393         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
394 
395     Error error;
396 
397     // Read hardware breakpoint and watchpoint information.
398     error = ReadHardwareDebugInfo ();
399 
400     if (error.Fail())
401         return LLDB_INVALID_INDEX32;
402 
403     uint32_t control_value = 0, bp_index = 0;
404 
405     // Check if size has a valid hardware breakpoint length.
406     // Thumb instructions are 2-bytes but we have no way here to determine
407     // if target address is a thumb or arm instruction.
408     // TODO: Add support for setting thumb mode hardware breakpoints
409     if (size != 4 && size != 2)
410         return LLDB_INVALID_INDEX32;
411 
412     // Setup control value
413     // Make the byte_mask into a valid Byte Address Select mask
414     control_value = 0xfu << 5;
415 
416     // Enable this breakpoint and make it stop in privileged or user mode;
417     control_value |= 7;
418 
419     // Make sure bits 1:0 are clear in our address
420     // This should be different once we support thumb here.
421     addr &= ~((lldb::addr_t)3);
422 
423     // Iterate over stored hardware breakpoints
424     // Find a free bp_index or update reference count if duplicate.
425     bp_index = LLDB_INVALID_INDEX32;
426 
427     for (uint32_t i = 0; i < m_max_hbp_supported; i++)
428     {
429         if ((m_hbr_regs[i].control & 1) == 0)
430         {
431             bp_index = i;  // Mark last free slot
432         }
433         else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value)
434         {
435             bp_index = i;  // Mark duplicate index
436             break;  // Stop searching here
437         }
438     }
439 
440      if (bp_index == LLDB_INVALID_INDEX32)
441          return LLDB_INVALID_INDEX32;
442 
443     // Add new or update existing watchpoint
444     if ((m_hbr_regs[bp_index].control & 1) == 0)
445     {
446         m_hbr_regs[bp_index].address = addr;
447         m_hbr_regs[bp_index].control = control_value;
448         m_hbr_regs[bp_index].refcount = 1;
449 
450         // PTRACE call to set corresponding hardware breakpoint register.
451         error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index);
452 
453         if (error.Fail())
454             return LLDB_INVALID_INDEX32;
455     }
456     else
457         m_hbr_regs[bp_index].refcount++;
458 
459     return bp_index;
460 }
461 
462 bool
463 NativeRegisterContextLinux_arm::ClearHardwareBreakpoint (uint32_t hw_idx)
464 {
465     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
466 
467     if (log)
468         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
469 
470     Error error;
471 
472     // Read hardware breakpoint and watchpoint information.
473     error = ReadHardwareDebugInfo ();
474 
475     if (error.Fail())
476         return LLDB_INVALID_INDEX32;
477 
478     if (hw_idx >= m_max_hbp_supported)
479         return false;
480 
481     // Update reference count if multiple references.
482     if (m_hbr_regs[hw_idx].refcount > 1)
483     {
484         m_hbr_regs[hw_idx].refcount--;
485         return true;
486     }
487     else if (m_hbr_regs[hw_idx].refcount == 1)
488     {
489         m_hbr_regs[hw_idx].control &= ~1;
490         m_hbr_regs[hw_idx].address = 0;
491         m_hbr_regs[hw_idx].refcount = 0;
492 
493         // PTRACE call to clear corresponding hardware breakpoint register.
494         WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx);
495 
496         if (error.Fail())
497             return LLDB_INVALID_INDEX32;
498 
499         return true;
500     }
501 
502     return false;
503 }
504 
505 uint32_t
506 NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints ()
507 {
508     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
509 
510     if (log)
511         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
512 
513     Error error;
514 
515     // Read hardware breakpoint and watchpoint information.
516     error = ReadHardwareDebugInfo ();
517 
518     if (error.Fail())
519         return LLDB_INVALID_INDEX32;
520 
521     return m_max_hwp_supported;
522 }
523 
524 uint32_t
525 NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags)
526 {
527     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
528 
529     if (log)
530         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
531 
532     Error error;
533 
534     // Read hardware breakpoint and watchpoint information.
535     error = ReadHardwareDebugInfo ();
536 
537     if (error.Fail())
538         return LLDB_INVALID_INDEX32;
539 
540     uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
541 
542     // Check if we are setting watchpoint other than read/write/access
543     // Also update watchpoint flag to match Arm write-read bit configuration.
544     switch (watch_flags)
545     {
546         case 1:
547             watch_flags = 2;
548             break;
549         case 2:
550             watch_flags = 1;
551             break;
552         case 3:
553             break;
554         default:
555             return LLDB_INVALID_INDEX32;
556     }
557 
558     // Can't watch zero bytes
559     // Can't watch more than 4 bytes per WVR/WCR pair
560 
561     if (size == 0 || size > 4)
562         return LLDB_INVALID_INDEX32;
563 
564     // We can only watch up to four bytes that follow a 4 byte aligned address
565     // per watchpoint register pair, so make sure we can properly encode this.
566     addr_word_offset = addr % 4;
567     byte_mask = ((1u << size) - 1u) << addr_word_offset;
568 
569     // Check if we need multiple watchpoint register
570     if (byte_mask > 0xfu)
571         return LLDB_INVALID_INDEX32;
572 
573     // Setup control value
574     // Make the byte_mask into a valid Byte Address Select mask
575     control_value = byte_mask << 5;
576 
577     //Turn on appropriate watchpoint flags read or write
578     control_value |= (watch_flags << 3);
579 
580     // Enable this watchpoint and make it stop in privileged or user mode;
581     control_value |= 7;
582 
583     // Make sure bits 1:0 are clear in our address
584     addr &= ~((lldb::addr_t)3);
585 
586     // Iterate over stored watchpoints
587     // Find a free wp_index or update reference count if duplicate.
588     wp_index = LLDB_INVALID_INDEX32;
589     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
590     {
591         if ((m_hwp_regs[i].control & 1) == 0)
592         {
593             wp_index = i; // Mark last free slot
594         }
595         else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value)
596         {
597             wp_index = i; // Mark duplicate index
598             break; // Stop searching here
599         }
600     }
601 
602      if (wp_index == LLDB_INVALID_INDEX32)
603         return LLDB_INVALID_INDEX32;
604 
605     // Add new or update existing watchpoint
606     if ((m_hwp_regs[wp_index].control & 1) == 0)
607     {
608         // Update watchpoint in local cache
609         m_hwp_regs[wp_index].address = addr;
610         m_hwp_regs[wp_index].control = control_value;
611         m_hwp_regs[wp_index].refcount = 1;
612 
613         // PTRACE call to set corresponding watchpoint register.
614         error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
615 
616         if (error.Fail())
617             return LLDB_INVALID_INDEX32;
618     }
619     else
620         m_hwp_regs[wp_index].refcount++;
621 
622     return wp_index;
623 }
624 
625 bool
626 NativeRegisterContextLinux_arm::ClearHardwareWatchpoint (uint32_t wp_index)
627 {
628     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
629 
630     if (log)
631         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
632 
633     Error error;
634 
635     // Read hardware breakpoint and watchpoint information.
636     error = ReadHardwareDebugInfo ();
637 
638     if (error.Fail())
639         return LLDB_INVALID_INDEX32;
640 
641     if (wp_index >= m_max_hwp_supported)
642         return false;
643 
644     // Update reference count if multiple references.
645     if (m_hwp_regs[wp_index].refcount > 1)
646     {
647         m_hwp_regs[wp_index].refcount--;
648         return true;
649     }
650     else if (m_hwp_regs[wp_index].refcount == 1)
651     {
652         // Update watchpoint in local cache
653         m_hwp_regs[wp_index].control &= ~1;
654         m_hwp_regs[wp_index].address = 0;
655         m_hwp_regs[wp_index].refcount = 0;
656 
657         // Ptrace call to update hardware debug registers
658         error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
659 
660         if (error.Fail())
661             return false;
662 
663         return true;
664     }
665 
666     return false;
667 }
668 
669 Error
670 NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints ()
671 {
672     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
673 
674     if (log)
675         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
676 
677     Error error;
678 
679     // Read hardware breakpoint and watchpoint information.
680     error = ReadHardwareDebugInfo ();
681 
682     if (error.Fail())
683         return error;
684 
685     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
686     {
687         if (m_hwp_regs[i].control & 0x01)
688         {
689             // Clear watchpoints in local cache
690             m_hwp_regs[i].control &= ~1;
691             m_hwp_regs[i].address = 0;
692             m_hwp_regs[i].refcount = 0;
693 
694             // Ptrace call to update hardware debug registers
695             error = WriteHardwareDebugRegs(eDREGTypeWATCH, i);
696 
697             if (error.Fail())
698                 return error;
699         }
700     }
701 
702     return Error();
703 }
704 
705 uint32_t
706 NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index)
707 {
708     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
709 
710     if (log)
711         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
712 
713     switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f)
714     {
715         case 0x01:
716             return 1;
717         case 0x03:
718             return 2;
719         case 0x07:
720             return 3;
721         case 0x0f:
722             return 4;
723         default:
724             return 0;
725     }
726 }
727 bool
728 NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index)
729 {
730     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
731 
732     if (log)
733         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
734 
735     if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
736         return true;
737     else
738         return false;
739 }
740 
741 Error
742 NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
743 {
744     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
745 
746     if (log)
747         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
748 
749     uint32_t watch_size;
750     lldb::addr_t watch_addr;
751 
752     for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
753     {
754         watch_size = GetWatchpointSize (wp_index);
755         watch_addr = m_hwp_regs[wp_index].address;
756 
757         if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
758             && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
759         {
760             return Error();
761         }
762     }
763 
764     wp_index = LLDB_INVALID_INDEX32;
765     return Error();
766 }
767 
768 lldb::addr_t
769 NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index)
770 {
771     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
772 
773     if (log)
774         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
775 
776     if (wp_index >= m_max_hwp_supported)
777         return LLDB_INVALID_ADDRESS;
778 
779     if (WatchpointIsEnabled(wp_index))
780         return m_hwp_regs[wp_index].address;
781     else
782         return LLDB_INVALID_ADDRESS;
783 }
784 
785 Error
786 NativeRegisterContextLinux_arm::ReadHardwareDebugInfo()
787 {
788     Error error;
789 
790     if (!m_refresh_hwdebug_info)
791     {
792         return Error();
793     }
794 
795     unsigned int cap_val;
796 
797     error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val, sizeof(unsigned int));
798 
799     if (error.Fail())
800         return error;
801 
802     m_max_hwp_supported = (cap_val >> 8) & 0xff;
803     m_max_hbp_supported = cap_val & 0xff;
804     m_refresh_hwdebug_info = false;
805 
806     return error;
807 }
808 
809 Error
810 NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_index)
811 {
812     Error error;
813 
814     lldb::addr_t *addr_buf;
815     uint32_t *ctrl_buf;
816 
817     if (hwbType == eDREGTypeWATCH)
818     {
819         addr_buf = &m_hwp_regs[hwb_index].address;
820         ctrl_buf = &m_hwp_regs[hwb_index].control;
821 
822         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
823                 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 1),
824                 addr_buf, sizeof(unsigned int));
825 
826         if (error.Fail())
827             return error;
828 
829         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
830                 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 2),
831                 ctrl_buf, sizeof(unsigned int));
832     }
833     else
834     {
835         addr_buf = &m_hwp_regs[hwb_index].address;
836         ctrl_buf = &m_hwp_regs[hwb_index].control;
837 
838         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
839                 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 1),
840                 addr_buf, sizeof(unsigned int));
841 
842         if (error.Fail())
843             return error;
844 
845         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
846                 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 2),
847                 ctrl_buf, sizeof(unsigned int));
848 
849     }
850 
851     return error;
852 }
853 
854 uint32_t
855 NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info) const
856 {
857     return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
858 }
859 
860 Error
861 NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
862                                                      const char* reg_name,
863                                                      const RegisterValue &value)
864 {
865     // PTRACE_POKEUSER don't work in the aarch64 liux kernel used on android devices (always return
866     // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR register set, modify
867     // the requested register and write it back. This approach is about 4 times slower but the
868     // performance overhead is negligible in comparision to processing time in lldb-server.
869     assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
870     if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
871         return Error("Register isn't fit into the size of the GPR area");
872 
873     Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
874     if (error.Fail())
875         return error;
876 
877     m_gpr_arm[offset / sizeof(uint32_t)] = value.GetAsUInt32();
878     return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm));
879 }
880 
881 Error
882 NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size)
883 {
884     return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS,
885                                              m_thread.GetID(),
886                                              nullptr,
887                                              buf,
888                                              buf_size);
889 }
890 
891 Error
892 NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size)
893 {
894     return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS,
895                                              m_thread.GetID(),
896                                              nullptr,
897                                              buf,
898                                              buf_size);
899 }
900 
901 #endif // defined(__arm__)
902