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