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 breakpoint
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         {
455             m_hbr_regs[bp_index].address = 0;
456             m_hbr_regs[bp_index].control &= ~1;
457             m_hbr_regs[bp_index].refcount = 0;
458 
459             return LLDB_INVALID_INDEX32;
460         }
461     }
462     else
463         m_hbr_regs[bp_index].refcount++;
464 
465     return bp_index;
466 }
467 
468 bool
469 NativeRegisterContextLinux_arm::ClearHardwareBreakpoint (uint32_t hw_idx)
470 {
471     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
472 
473     if (log)
474         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
475 
476     Error error;
477 
478     // Read hardware breakpoint and watchpoint information.
479     error = ReadHardwareDebugInfo ();
480 
481     if (error.Fail())
482         return false;
483 
484     if (hw_idx >= m_max_hbp_supported)
485         return false;
486 
487     // Update reference count if multiple references.
488     if (m_hbr_regs[hw_idx].refcount > 1)
489     {
490         m_hbr_regs[hw_idx].refcount--;
491         return true;
492     }
493     else if (m_hbr_regs[hw_idx].refcount == 1)
494     {
495         // Create a backup we can revert to in case of failure.
496         lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address;
497         uint32_t tempControl = m_hbr_regs[hw_idx].control;
498         uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount;
499 
500         m_hbr_regs[hw_idx].control &= ~1;
501         m_hbr_regs[hw_idx].address = 0;
502         m_hbr_regs[hw_idx].refcount = 0;
503 
504         // PTRACE call to clear corresponding hardware breakpoint register.
505         WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx);
506 
507         if (error.Fail())
508         {
509             m_hbr_regs[hw_idx].control = tempControl;
510             m_hbr_regs[hw_idx].address = tempAddr;
511             m_hbr_regs[hw_idx].refcount = tempRefCount;
512 
513             return false;
514         }
515 
516         return true;
517     }
518 
519     return false;
520 }
521 
522 uint32_t
523 NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints ()
524 {
525     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
526 
527     if (log)
528         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
529 
530     Error error;
531 
532     // Read hardware breakpoint and watchpoint information.
533     error = ReadHardwareDebugInfo ();
534 
535     if (error.Fail())
536         return LLDB_INVALID_INDEX32;
537 
538     return m_max_hwp_supported;
539 }
540 
541 uint32_t
542 NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags)
543 {
544     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
545 
546     if (log)
547         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
548 
549     Error error;
550 
551     // Read hardware breakpoint and watchpoint information.
552     error = ReadHardwareDebugInfo ();
553 
554     if (error.Fail())
555         return LLDB_INVALID_INDEX32;
556 
557     uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
558 
559     // Check if we are setting watchpoint other than read/write/access
560     // Also update watchpoint flag to match Arm write-read bit configuration.
561     switch (watch_flags)
562     {
563         case 1:
564             watch_flags = 2;
565             break;
566         case 2:
567             watch_flags = 1;
568             break;
569         case 3:
570             break;
571         default:
572             return LLDB_INVALID_INDEX32;
573     }
574 
575     // Can't watch zero bytes
576     // Can't watch more than 4 bytes per WVR/WCR pair
577 
578     if (size == 0 || size > 4)
579         return LLDB_INVALID_INDEX32;
580 
581     // We can only watch up to four bytes that follow a 4 byte aligned address
582     // per watchpoint register pair, so make sure we can properly encode this.
583     addr_word_offset = addr % 4;
584     byte_mask = ((1u << size) - 1u) << addr_word_offset;
585 
586     // Check if we need multiple watchpoint register
587     if (byte_mask > 0xfu)
588         return LLDB_INVALID_INDEX32;
589 
590     // Setup control value
591     // Make the byte_mask into a valid Byte Address Select mask
592     control_value = byte_mask << 5;
593 
594     //Turn on appropriate watchpoint flags read or write
595     control_value |= (watch_flags << 3);
596 
597     // Enable this watchpoint and make it stop in privileged or user mode;
598     control_value |= 7;
599 
600     // Make sure bits 1:0 are clear in our address
601     addr &= ~((lldb::addr_t)3);
602 
603     // Iterate over stored watchpoints
604     // Find a free wp_index or update reference count if duplicate.
605     wp_index = LLDB_INVALID_INDEX32;
606     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
607     {
608         if ((m_hwp_regs[i].control & 1) == 0)
609         {
610             wp_index = i; // Mark last free slot
611         }
612         else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value)
613         {
614             wp_index = i; // Mark duplicate index
615             break; // Stop searching here
616         }
617     }
618 
619      if (wp_index == LLDB_INVALID_INDEX32)
620         return LLDB_INVALID_INDEX32;
621 
622     // Add new or update existing watchpoint
623     if ((m_hwp_regs[wp_index].control & 1) == 0)
624     {
625         // Update watchpoint in local cache
626         m_hwp_regs[wp_index].address = addr;
627         m_hwp_regs[wp_index].control = control_value;
628         m_hwp_regs[wp_index].refcount = 1;
629 
630         // PTRACE call to set corresponding watchpoint register.
631         error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
632 
633         if (error.Fail())
634         {
635             m_hwp_regs[wp_index].address = 0;
636             m_hwp_regs[wp_index].control &= ~1;
637             m_hwp_regs[wp_index].refcount = 0;
638 
639             return LLDB_INVALID_INDEX32;
640         }
641     }
642     else
643         m_hwp_regs[wp_index].refcount++;
644 
645     return wp_index;
646 }
647 
648 bool
649 NativeRegisterContextLinux_arm::ClearHardwareWatchpoint (uint32_t wp_index)
650 {
651     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
652 
653     if (log)
654         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
655 
656     Error error;
657 
658     // Read hardware breakpoint and watchpoint information.
659     error = ReadHardwareDebugInfo ();
660 
661     if (error.Fail())
662         return false;
663 
664     if (wp_index >= m_max_hwp_supported)
665         return false;
666 
667     // Update reference count if multiple references.
668     if (m_hwp_regs[wp_index].refcount > 1)
669     {
670         m_hwp_regs[wp_index].refcount--;
671         return true;
672     }
673     else if (m_hwp_regs[wp_index].refcount == 1)
674     {
675         // Create a backup we can revert to in case of failure.
676         lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
677         uint32_t tempControl = m_hwp_regs[wp_index].control;
678         uint32_t tempRefCount = m_hwp_regs[wp_index].refcount;
679 
680         // Update watchpoint in local cache
681         m_hwp_regs[wp_index].control &= ~1;
682         m_hwp_regs[wp_index].address = 0;
683         m_hwp_regs[wp_index].refcount = 0;
684 
685         // Ptrace call to update hardware debug registers
686         error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
687 
688         if (error.Fail())
689         {
690             m_hwp_regs[wp_index].control = tempControl;
691             m_hwp_regs[wp_index].address = tempAddr;
692             m_hwp_regs[wp_index].refcount = tempRefCount;
693 
694             return false;
695         }
696 
697         return true;
698     }
699 
700     return false;
701 }
702 
703 Error
704 NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints ()
705 {
706     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
707 
708     if (log)
709         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
710 
711     Error error;
712 
713     // Read hardware breakpoint and watchpoint information.
714     error = ReadHardwareDebugInfo ();
715 
716     if (error.Fail())
717         return error;
718 
719     lldb::addr_t tempAddr = 0;
720     uint32_t tempControl = 0, tempRefCount = 0;
721 
722     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
723     {
724         if (m_hwp_regs[i].control & 0x01)
725         {
726             // Create a backup we can revert to in case of failure.
727             tempAddr = m_hwp_regs[i].address;
728             tempControl = m_hwp_regs[i].control;
729             tempRefCount = m_hwp_regs[i].refcount;
730 
731             // Clear watchpoints in local cache
732             m_hwp_regs[i].control &= ~1;
733             m_hwp_regs[i].address = 0;
734             m_hwp_regs[i].refcount = 0;
735 
736             // Ptrace call to update hardware debug registers
737             error = WriteHardwareDebugRegs(eDREGTypeWATCH, i);
738 
739             if (error.Fail())
740             {
741                 m_hwp_regs[i].control = tempControl;
742                 m_hwp_regs[i].address = tempAddr;
743                 m_hwp_regs[i].refcount = tempRefCount;
744 
745                 return error;
746             }
747         }
748     }
749 
750     return Error();
751 }
752 
753 uint32_t
754 NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index)
755 {
756     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
757 
758     if (log)
759         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
760 
761     switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f)
762     {
763         case 0x01:
764             return 1;
765         case 0x03:
766             return 2;
767         case 0x07:
768             return 3;
769         case 0x0f:
770             return 4;
771         default:
772             return 0;
773     }
774 }
775 bool
776 NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index)
777 {
778     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
779 
780     if (log)
781         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
782 
783     if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
784         return true;
785     else
786         return false;
787 }
788 
789 Error
790 NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
791 {
792     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
793 
794     if (log)
795         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
796 
797     uint32_t watch_size;
798     lldb::addr_t watch_addr;
799 
800     for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
801     {
802         watch_size = GetWatchpointSize (wp_index);
803         watch_addr = m_hwp_regs[wp_index].address;
804 
805         if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
806             && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
807         {
808             return Error();
809         }
810     }
811 
812     wp_index = LLDB_INVALID_INDEX32;
813     return Error();
814 }
815 
816 lldb::addr_t
817 NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index)
818 {
819     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
820 
821     if (log)
822         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
823 
824     if (wp_index >= m_max_hwp_supported)
825         return LLDB_INVALID_ADDRESS;
826 
827     if (WatchpointIsEnabled(wp_index))
828         return m_hwp_regs[wp_index].address;
829     else
830         return LLDB_INVALID_ADDRESS;
831 }
832 
833 Error
834 NativeRegisterContextLinux_arm::ReadHardwareDebugInfo()
835 {
836     Error error;
837 
838     if (!m_refresh_hwdebug_info)
839     {
840         return Error();
841     }
842 
843     unsigned int cap_val;
844 
845     error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val, sizeof(unsigned int));
846 
847     if (error.Fail())
848         return error;
849 
850     m_max_hwp_supported = (cap_val >> 8) & 0xff;
851     m_max_hbp_supported = cap_val & 0xff;
852     m_refresh_hwdebug_info = false;
853 
854     return error;
855 }
856 
857 Error
858 NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_index)
859 {
860     Error error;
861 
862     lldb::addr_t *addr_buf;
863     uint32_t *ctrl_buf;
864 
865     if (hwbType == eDREGTypeWATCH)
866     {
867         addr_buf = &m_hwp_regs[hwb_index].address;
868         ctrl_buf = &m_hwp_regs[hwb_index].control;
869 
870         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
871                 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 1),
872                 addr_buf, sizeof(unsigned int));
873 
874         if (error.Fail())
875             return error;
876 
877         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
878                 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 2),
879                 ctrl_buf, sizeof(unsigned int));
880     }
881     else
882     {
883         addr_buf = &m_hwp_regs[hwb_index].address;
884         ctrl_buf = &m_hwp_regs[hwb_index].control;
885 
886         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
887                 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 1),
888                 addr_buf, sizeof(unsigned int));
889 
890         if (error.Fail())
891             return error;
892 
893         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
894                 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 2),
895                 ctrl_buf, sizeof(unsigned int));
896 
897     }
898 
899     return error;
900 }
901 
902 uint32_t
903 NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info) const
904 {
905     return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
906 }
907 
908 Error
909 NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
910                                                      const char* reg_name,
911                                                      const RegisterValue &value)
912 {
913     // PTRACE_POKEUSER don't work in the aarch64 liux kernel used on android devices (always return
914     // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR register set, modify
915     // the requested register and write it back. This approach is about 4 times slower but the
916     // performance overhead is negligible in comparision to processing time in lldb-server.
917     assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
918     if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
919         return Error("Register isn't fit into the size of the GPR area");
920 
921     Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
922     if (error.Fail())
923         return error;
924 
925     m_gpr_arm[offset / sizeof(uint32_t)] = value.GetAsUInt32();
926     return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm));
927 }
928 
929 Error
930 NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size)
931 {
932     return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS,
933                                              m_thread.GetID(),
934                                              nullptr,
935                                              buf,
936                                              buf_size);
937 }
938 
939 Error
940 NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size)
941 {
942     return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS,
943                                              m_thread.GetID(),
944                                              nullptr,
945                                              buf,
946                                              buf_size);
947 }
948 
949 #endif // defined(__arm__)
950