13f57216cSOmair Javaid //===-- NativeRegisterContextLinux_arm.cpp --------------------*- C++ -*-===//
23f57216cSOmair Javaid //
33f57216cSOmair Javaid //                     The LLVM Compiler Infrastructure
43f57216cSOmair Javaid //
53f57216cSOmair Javaid // This file is distributed under the University of Illinois Open Source
63f57216cSOmair Javaid // License. See LICENSE.TXT for details.
73f57216cSOmair Javaid //
83f57216cSOmair Javaid //===----------------------------------------------------------------------===//
93f57216cSOmair Javaid 
10068f8a7eSTamas Berghammer #if defined(__arm__)
11068f8a7eSTamas Berghammer 
123f57216cSOmair Javaid #include "NativeRegisterContextLinux_arm.h"
133f57216cSOmair Javaid 
143f57216cSOmair Javaid #include "lldb/Core/DataBufferHeap.h"
153f57216cSOmair Javaid #include "lldb/Core/Error.h"
16*2441aecdSOmair Javaid #include "lldb/Core/Log.h"
173f57216cSOmair Javaid #include "lldb/Core/RegisterValue.h"
18068f8a7eSTamas Berghammer 
19068f8a7eSTamas Berghammer #include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
203f57216cSOmair Javaid 
213f57216cSOmair Javaid #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
223f57216cSOmair Javaid 
23*2441aecdSOmair Javaid #ifndef PTRACE_GETHBPREGS
24*2441aecdSOmair Javaid   #define PTRACE_GETHBPREGS 29
25*2441aecdSOmair Javaid   #define PTRACE_SETHBPREGS 30
26*2441aecdSOmair Javaid #endif
27*2441aecdSOmair Javaid #if !defined(PTRACE_TYPE_ARG3)
28*2441aecdSOmair Javaid   #define PTRACE_TYPE_ARG3 void *
29*2441aecdSOmair Javaid #endif
30*2441aecdSOmair Javaid #if !defined(PTRACE_TYPE_ARG4)
31*2441aecdSOmair Javaid   #define PTRACE_TYPE_ARG4 void *
32*2441aecdSOmair Javaid #endif
33*2441aecdSOmair Javaid 
343f57216cSOmair Javaid using namespace lldb;
353f57216cSOmair Javaid using namespace lldb_private;
363f57216cSOmair Javaid using namespace lldb_private::process_linux;
373f57216cSOmair Javaid 
383f57216cSOmair Javaid // arm general purpose registers.
393f57216cSOmair Javaid static const uint32_t g_gpr_regnums_arm[] =
403f57216cSOmair Javaid {
413f57216cSOmair Javaid     gpr_r0_arm,
423f57216cSOmair Javaid     gpr_r1_arm,
433f57216cSOmair Javaid     gpr_r2_arm,
443f57216cSOmair Javaid     gpr_r3_arm,
453f57216cSOmair Javaid     gpr_r4_arm,
463f57216cSOmair Javaid     gpr_r5_arm,
473f57216cSOmair Javaid     gpr_r6_arm,
483f57216cSOmair Javaid     gpr_r7_arm,
493f57216cSOmair Javaid     gpr_r8_arm,
503f57216cSOmair Javaid     gpr_r9_arm,
513f57216cSOmair Javaid     gpr_r10_arm,
523f57216cSOmair Javaid     gpr_r11_arm,
533f57216cSOmair Javaid     gpr_r12_arm,
543f57216cSOmair Javaid     gpr_sp_arm,
553f57216cSOmair Javaid     gpr_lr_arm,
563f57216cSOmair Javaid     gpr_pc_arm,
573f57216cSOmair Javaid     gpr_cpsr_arm,
583f57216cSOmair Javaid     LLDB_INVALID_REGNUM // register sets need to end with this flag
593f57216cSOmair Javaid };
603f57216cSOmair Javaid static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \
613f57216cSOmair Javaid               "g_gpr_regnums_arm has wrong number of register infos");
623f57216cSOmair Javaid 
633f57216cSOmair Javaid // arm floating point registers.
643f57216cSOmair Javaid static const uint32_t g_fpu_regnums_arm[] =
653f57216cSOmair Javaid {
663f57216cSOmair Javaid     fpu_s0_arm,
673f57216cSOmair Javaid     fpu_s1_arm,
683f57216cSOmair Javaid     fpu_s2_arm,
693f57216cSOmair Javaid     fpu_s3_arm,
703f57216cSOmair Javaid     fpu_s4_arm,
713f57216cSOmair Javaid     fpu_s5_arm,
723f57216cSOmair Javaid     fpu_s6_arm,
733f57216cSOmair Javaid     fpu_s7_arm,
743f57216cSOmair Javaid     fpu_s8_arm,
753f57216cSOmair Javaid     fpu_s9_arm,
763f57216cSOmair Javaid     fpu_s10_arm,
773f57216cSOmair Javaid     fpu_s11_arm,
783f57216cSOmair Javaid     fpu_s12_arm,
793f57216cSOmair Javaid     fpu_s13_arm,
803f57216cSOmair Javaid     fpu_s14_arm,
813f57216cSOmair Javaid     fpu_s15_arm,
823f57216cSOmair Javaid     fpu_s16_arm,
833f57216cSOmair Javaid     fpu_s17_arm,
843f57216cSOmair Javaid     fpu_s18_arm,
853f57216cSOmair Javaid     fpu_s19_arm,
863f57216cSOmair Javaid     fpu_s20_arm,
873f57216cSOmair Javaid     fpu_s21_arm,
883f57216cSOmair Javaid     fpu_s22_arm,
893f57216cSOmair Javaid     fpu_s23_arm,
903f57216cSOmair Javaid     fpu_s24_arm,
913f57216cSOmair Javaid     fpu_s25_arm,
923f57216cSOmair Javaid     fpu_s26_arm,
933f57216cSOmair Javaid     fpu_s27_arm,
943f57216cSOmair Javaid     fpu_s28_arm,
953f57216cSOmair Javaid     fpu_s29_arm,
963f57216cSOmair Javaid     fpu_s30_arm,
973f57216cSOmair Javaid     fpu_s31_arm,
983f57216cSOmair Javaid     fpu_fpscr_arm,
993f57216cSOmair Javaid     LLDB_INVALID_REGNUM // register sets need to end with this flag
1003f57216cSOmair Javaid };
1013f57216cSOmair Javaid static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \
1023f57216cSOmair Javaid               "g_fpu_regnums_arm has wrong number of register infos");
1033f57216cSOmair Javaid 
1043f57216cSOmair Javaid namespace {
1053f57216cSOmair Javaid     // Number of register sets provided by this context.
1063f57216cSOmair Javaid     enum
1073f57216cSOmair Javaid     {
1083f57216cSOmair Javaid         k_num_register_sets = 2
1093f57216cSOmair Javaid     };
1103f57216cSOmair Javaid }
1113f57216cSOmair Javaid 
1123f57216cSOmair Javaid // Register sets for arm.
1133f57216cSOmair Javaid static const RegisterSet
1143f57216cSOmair Javaid g_reg_sets_arm[k_num_register_sets] =
1153f57216cSOmair Javaid {
1163f57216cSOmair Javaid     { "General Purpose Registers",  "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm },
1173f57216cSOmair Javaid     { "Floating Point Registers",   "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
1183f57216cSOmair Javaid };
1193f57216cSOmair Javaid 
120068f8a7eSTamas Berghammer NativeRegisterContextLinux*
121068f8a7eSTamas Berghammer NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
1223f57216cSOmair Javaid                                                                  NativeThreadProtocol &native_thread,
123068f8a7eSTamas Berghammer                                                                  uint32_t concrete_frame_idx)
1243f57216cSOmair Javaid {
125068f8a7eSTamas Berghammer     return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
126068f8a7eSTamas Berghammer }
127068f8a7eSTamas Berghammer 
128068f8a7eSTamas Berghammer NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
129068f8a7eSTamas Berghammer                                                                 NativeThreadProtocol &native_thread,
130068f8a7eSTamas Berghammer                                                                 uint32_t concrete_frame_idx) :
131068f8a7eSTamas Berghammer     NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm(target_arch))
132068f8a7eSTamas Berghammer {
133068f8a7eSTamas Berghammer     switch (target_arch.GetMachine())
1343f57216cSOmair Javaid     {
1353f57216cSOmair Javaid         case llvm::Triple::arm:
1363f57216cSOmair Javaid             m_reg_info.num_registers     = k_num_registers_arm;
1373f57216cSOmair Javaid             m_reg_info.num_gpr_registers = k_num_gpr_registers_arm;
1383f57216cSOmair Javaid             m_reg_info.num_fpr_registers = k_num_fpr_registers_arm;
1393f57216cSOmair Javaid             m_reg_info.last_gpr          = k_last_gpr_arm;
1403f57216cSOmair Javaid             m_reg_info.first_fpr         = k_first_fpr_arm;
1413f57216cSOmair Javaid             m_reg_info.last_fpr          = k_last_fpr_arm;
1423f57216cSOmair Javaid             m_reg_info.first_fpr_v       = fpu_s0_arm;
1433f57216cSOmair Javaid             m_reg_info.last_fpr_v        = fpu_s31_arm;
1443f57216cSOmair Javaid             m_reg_info.gpr_flags         = gpr_cpsr_arm;
1453f57216cSOmair Javaid             break;
1463f57216cSOmair Javaid         default:
1473f57216cSOmair Javaid             assert(false && "Unhandled target architecture.");
1483f57216cSOmair Javaid             break;
1493f57216cSOmair Javaid     }
1503f57216cSOmair Javaid 
1513f57216cSOmair Javaid     ::memset(&m_fpr, 0, sizeof (m_fpr));
1523f57216cSOmair Javaid     ::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm));
153*2441aecdSOmair Javaid     ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs));
154*2441aecdSOmair Javaid 
155*2441aecdSOmair Javaid     // 16 is just a maximum value, query hardware for actual watchpoint count
156*2441aecdSOmair Javaid     m_max_hwp_supported = 16;
157*2441aecdSOmair Javaid     m_max_hbp_supported = 16;
158*2441aecdSOmair Javaid     m_refresh_hwdebug_info = true;
1593f57216cSOmair Javaid }
1603f57216cSOmair Javaid 
1613f57216cSOmair Javaid uint32_t
1623f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetRegisterSetCount () const
1633f57216cSOmair Javaid {
1643f57216cSOmair Javaid     return k_num_register_sets;
1653f57216cSOmair Javaid }
1663f57216cSOmair Javaid 
1671f149204STamas Berghammer uint32_t
1681f149204STamas Berghammer NativeRegisterContextLinux_arm::GetUserRegisterCount() const
1691f149204STamas Berghammer {
1701f149204STamas Berghammer     uint32_t count = 0;
1711f149204STamas Berghammer     for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
1721f149204STamas Berghammer         count += g_reg_sets_arm[set_index].num_registers;
1731f149204STamas Berghammer     return count;
1741f149204STamas Berghammer }
1751f149204STamas Berghammer 
1763f57216cSOmair Javaid const RegisterSet *
1773f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const
1783f57216cSOmair Javaid {
1793f57216cSOmair Javaid     if (set_index < k_num_register_sets)
1803f57216cSOmair Javaid         return &g_reg_sets_arm[set_index];
1813f57216cSOmair Javaid 
1823f57216cSOmair Javaid     return nullptr;
1833f57216cSOmair Javaid }
1843f57216cSOmair Javaid 
1853f57216cSOmair Javaid Error
1863f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
1873f57216cSOmair Javaid {
1883f57216cSOmair Javaid     Error error;
1893f57216cSOmair Javaid 
1903f57216cSOmair Javaid     if (!reg_info)
1913f57216cSOmair Javaid     {
1923f57216cSOmair Javaid         error.SetErrorString ("reg_info NULL");
1933f57216cSOmair Javaid         return error;
1943f57216cSOmair Javaid     }
1953f57216cSOmair Javaid 
1963f57216cSOmair Javaid     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
1973f57216cSOmair Javaid 
1983f57216cSOmair Javaid     if (IsFPR(reg))
1993f57216cSOmair Javaid     {
200068f8a7eSTamas Berghammer         error = ReadFPR();
201068f8a7eSTamas Berghammer         if (error.Fail())
2023f57216cSOmair Javaid             return error;
2033f57216cSOmair Javaid     }
2043f57216cSOmair Javaid     else
2053f57216cSOmair Javaid     {
2063f57216cSOmair Javaid         uint32_t full_reg = reg;
2073f57216cSOmair Javaid         bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
2083f57216cSOmair Javaid 
2093f57216cSOmair Javaid         if (is_subreg)
2103f57216cSOmair Javaid         {
2113f57216cSOmair Javaid             // Read the full aligned 64-bit register.
2123f57216cSOmair Javaid             full_reg = reg_info->invalidate_regs[0];
2133f57216cSOmair Javaid         }
2143f57216cSOmair Javaid 
2153f57216cSOmair Javaid         error = ReadRegisterRaw(full_reg, reg_value);
2163f57216cSOmair Javaid 
2173f57216cSOmair Javaid         if (error.Success ())
2183f57216cSOmair Javaid         {
2193f57216cSOmair Javaid             // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
2203f57216cSOmair Javaid             if (is_subreg && (reg_info->byte_offset & 0x1))
2213f57216cSOmair Javaid                 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
2223f57216cSOmair Javaid 
2233f57216cSOmair Javaid             // If our return byte size was greater than the return value reg size, then
2243f57216cSOmair Javaid             // use the type specified by reg_info rather than the uint64_t default
2253f57216cSOmair Javaid             if (reg_value.GetByteSize() > reg_info->byte_size)
2263f57216cSOmair Javaid                 reg_value.SetType(reg_info);
2273f57216cSOmair Javaid         }
2283f57216cSOmair Javaid         return error;
2293f57216cSOmair Javaid     }
2303f57216cSOmair Javaid 
2313f57216cSOmair Javaid     // Get pointer to m_fpr variable and set the data from it.
2323f57216cSOmair Javaid     assert (reg_info->byte_offset < sizeof m_fpr);
2333f57216cSOmair Javaid     uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
2343f57216cSOmair Javaid     switch (reg_info->byte_size)
2353f57216cSOmair Javaid     {
2363f57216cSOmair Javaid         case 2:
2373f57216cSOmair Javaid             reg_value.SetUInt16(*(uint16_t *)src);
2383f57216cSOmair Javaid             break;
2393f57216cSOmair Javaid         case 4:
2403f57216cSOmair Javaid             reg_value.SetUInt32(*(uint32_t *)src);
2413f57216cSOmair Javaid             break;
2423f57216cSOmair Javaid         case 8:
2433f57216cSOmair Javaid             reg_value.SetUInt64(*(uint64_t *)src);
2443f57216cSOmair Javaid             break;
2453f57216cSOmair Javaid         default:
2463f57216cSOmair Javaid             assert(false && "Unhandled data size.");
2473f57216cSOmair Javaid             error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
2483f57216cSOmair Javaid             break;
2493f57216cSOmair Javaid     }
2503f57216cSOmair Javaid 
2513f57216cSOmair Javaid     return error;
2523f57216cSOmair Javaid }
2533f57216cSOmair Javaid 
2543f57216cSOmair Javaid Error
2553f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
2563f57216cSOmair Javaid {
2573f57216cSOmair Javaid     if (!reg_info)
2583f57216cSOmair Javaid         return Error ("reg_info NULL");
2593f57216cSOmair Javaid 
2603f57216cSOmair Javaid     const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
2613f57216cSOmair Javaid     if (reg_index == LLDB_INVALID_REGNUM)
2623f57216cSOmair Javaid         return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
2633f57216cSOmair Javaid 
2643f57216cSOmair Javaid     if (IsGPR(reg_index))
2653f57216cSOmair Javaid         return WriteRegisterRaw(reg_index, reg_value);
2663f57216cSOmair Javaid 
2673f57216cSOmair Javaid     if (IsFPR(reg_index))
2683f57216cSOmair Javaid     {
2693f57216cSOmair Javaid         // Get pointer to m_fpr variable and set the data to it.
2703f57216cSOmair Javaid         assert (reg_info->byte_offset < sizeof(m_fpr));
2713f57216cSOmair Javaid         uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
2723f57216cSOmair Javaid         switch (reg_info->byte_size)
2733f57216cSOmair Javaid         {
2743f57216cSOmair Javaid             case 2:
2753f57216cSOmair Javaid                 *(uint16_t *)dst = reg_value.GetAsUInt16();
2763f57216cSOmair Javaid                 break;
2773f57216cSOmair Javaid             case 4:
2783f57216cSOmair Javaid                 *(uint32_t *)dst = reg_value.GetAsUInt32();
2793f57216cSOmair Javaid                 break;
2803f57216cSOmair Javaid             case 8:
2813f57216cSOmair Javaid                 *(uint64_t *)dst = reg_value.GetAsUInt64();
2823f57216cSOmair Javaid                 break;
2833f57216cSOmair Javaid             default:
2843f57216cSOmair Javaid                 assert(false && "Unhandled data size.");
2853f57216cSOmair Javaid                 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
2863f57216cSOmair Javaid         }
2873f57216cSOmair Javaid 
288068f8a7eSTamas Berghammer         Error error = WriteFPR();
289068f8a7eSTamas Berghammer         if (error.Fail())
290068f8a7eSTamas Berghammer             return error;
2913f57216cSOmair Javaid 
2923f57216cSOmair Javaid         return Error ();
2933f57216cSOmair Javaid     }
2943f57216cSOmair Javaid 
2953f57216cSOmair Javaid     return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
2963f57216cSOmair Javaid }
2973f57216cSOmair Javaid 
2983f57216cSOmair Javaid Error
2993f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
3003f57216cSOmair Javaid {
3013f57216cSOmair Javaid     Error error;
3023f57216cSOmair Javaid 
3033f57216cSOmair Javaid     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
3043f57216cSOmair Javaid     if (!data_sp)
305bef47e49SGreg Clayton         return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE);
3063f57216cSOmair Javaid 
307068f8a7eSTamas Berghammer     error = ReadGPR();
308068f8a7eSTamas Berghammer     if (error.Fail())
3093f57216cSOmair Javaid         return error;
3103f57216cSOmair Javaid 
311068f8a7eSTamas Berghammer     error = ReadFPR();
312068f8a7eSTamas Berghammer     if (error.Fail())
3133f57216cSOmair Javaid         return error;
3143f57216cSOmair Javaid 
3153f57216cSOmair Javaid     uint8_t *dst = data_sp->GetBytes ();
3163f57216cSOmair Javaid     if (dst == nullptr)
3173f57216cSOmair Javaid     {
318bef47e49SGreg Clayton         error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE);
3193f57216cSOmair Javaid         return error;
3203f57216cSOmair Javaid     }
3213f57216cSOmair Javaid 
3223f57216cSOmair Javaid     ::memcpy (dst, &m_gpr_arm, GetGPRSize());
3233f57216cSOmair Javaid     dst += GetGPRSize();
3243f57216cSOmair Javaid     ::memcpy (dst, &m_fpr, sizeof(m_fpr));
3253f57216cSOmair Javaid 
3263f57216cSOmair Javaid     return error;
3273f57216cSOmair Javaid }
3283f57216cSOmair Javaid 
3293f57216cSOmair Javaid Error
3303f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
3313f57216cSOmair Javaid {
3323f57216cSOmair Javaid     Error error;
3333f57216cSOmair Javaid 
3343f57216cSOmair Javaid     if (!data_sp)
3353f57216cSOmair Javaid     {
3363f57216cSOmair Javaid         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
3373f57216cSOmair Javaid         return error;
3383f57216cSOmair Javaid     }
3393f57216cSOmair Javaid 
3403f57216cSOmair Javaid     if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
3413f57216cSOmair Javaid     {
342bef47e49SGreg Clayton         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 ());
3433f57216cSOmair Javaid         return error;
3443f57216cSOmair Javaid     }
3453f57216cSOmair Javaid 
3463f57216cSOmair Javaid 
3473f57216cSOmair Javaid     uint8_t *src = data_sp->GetBytes ();
3483f57216cSOmair Javaid     if (src == nullptr)
3493f57216cSOmair Javaid     {
3503f57216cSOmair Javaid         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
3513f57216cSOmair Javaid         return error;
3523f57216cSOmair Javaid     }
3533f57216cSOmair Javaid     ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ());
3543f57216cSOmair Javaid 
355068f8a7eSTamas Berghammer     error = WriteGPR();
356068f8a7eSTamas Berghammer     if (error.Fail())
3573f57216cSOmair Javaid         return error;
3583f57216cSOmair Javaid 
3593f57216cSOmair Javaid     src += GetRegisterInfoInterface ().GetGPRSize ();
3603f57216cSOmair Javaid     ::memcpy (&m_fpr, src, sizeof(m_fpr));
3613f57216cSOmair Javaid 
362068f8a7eSTamas Berghammer     error = WriteFPR();
3633f57216cSOmair Javaid     if (error.Fail())
3643f57216cSOmair Javaid         return error;
3653f57216cSOmair Javaid 
3663f57216cSOmair Javaid     return error;
3673f57216cSOmair Javaid }
3683f57216cSOmair Javaid 
3693f57216cSOmair Javaid bool
3703f57216cSOmair Javaid NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const
3713f57216cSOmair Javaid {
3723f57216cSOmair Javaid     return reg <= m_reg_info.last_gpr;   // GPR's come first.
3733f57216cSOmair Javaid }
3743f57216cSOmair Javaid 
3753f57216cSOmair Javaid bool
3763f57216cSOmair Javaid NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const
3773f57216cSOmair Javaid {
3783f57216cSOmair Javaid     return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
3793f57216cSOmair Javaid }
3803f57216cSOmair Javaid 
381*2441aecdSOmair Javaid uint32_t
382*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
383*2441aecdSOmair Javaid {
384*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
385*2441aecdSOmair Javaid 
386*2441aecdSOmair Javaid     if (log)
387*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
388*2441aecdSOmair Javaid 
389*2441aecdSOmair Javaid     Error error;
390*2441aecdSOmair Javaid 
391*2441aecdSOmair Javaid     // Read hardware breakpoint and watchpoint information.
392*2441aecdSOmair Javaid     error = ReadHardwareDebugInfo ();
393*2441aecdSOmair Javaid 
394*2441aecdSOmair Javaid     if (error.Fail())
395*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
396*2441aecdSOmair Javaid 
397*2441aecdSOmair Javaid     uint32_t control_value = 0, bp_index = 0;
398*2441aecdSOmair Javaid 
399*2441aecdSOmair Javaid     // Check if size has a valid hardware breakpoint length.
400*2441aecdSOmair Javaid     // Thumb instructions are 2-bytes but we have no way here to determine
401*2441aecdSOmair Javaid     // if target address is a thumb or arm instruction.
402*2441aecdSOmair Javaid     // TODO: Add support for setting thumb mode hardware breakpoints
403*2441aecdSOmair Javaid     if (size != 4 && size != 2)
404*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
405*2441aecdSOmair Javaid 
406*2441aecdSOmair Javaid     // Setup control value
407*2441aecdSOmair Javaid     // Make the byte_mask into a valid Byte Address Select mask
408*2441aecdSOmair Javaid     control_value = 0xfu << 5;
409*2441aecdSOmair Javaid 
410*2441aecdSOmair Javaid     // Enable this breakpoint and make it stop in privileged or user mode;
411*2441aecdSOmair Javaid     control_value |= 7;
412*2441aecdSOmair Javaid 
413*2441aecdSOmair Javaid     // Make sure bits 1:0 are clear in our address
414*2441aecdSOmair Javaid     // This should be different once we support thumb here.
415*2441aecdSOmair Javaid     addr &= ~((lldb::addr_t)3);
416*2441aecdSOmair Javaid 
417*2441aecdSOmair Javaid     // Iterate over stored hardware breakpoints
418*2441aecdSOmair Javaid     // Find a free bp_index or update reference count if duplicate.
419*2441aecdSOmair Javaid     bp_index = LLDB_INVALID_INDEX32;
420*2441aecdSOmair Javaid 
421*2441aecdSOmair Javaid     for (uint32_t i = 0; i < m_max_hbp_supported; i++)
422*2441aecdSOmair Javaid     {
423*2441aecdSOmair Javaid         if ((m_hbr_regs[i].control & 1) == 0)
424*2441aecdSOmair Javaid         {
425*2441aecdSOmair Javaid             bp_index = i;  // Mark last free slot
426*2441aecdSOmair Javaid         }
427*2441aecdSOmair Javaid         else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value)
428*2441aecdSOmair Javaid         {
429*2441aecdSOmair Javaid             bp_index = i;  // Mark duplicate index
430*2441aecdSOmair Javaid             break;  // Stop searching here
431*2441aecdSOmair Javaid         }
432*2441aecdSOmair Javaid     }
433*2441aecdSOmair Javaid 
434*2441aecdSOmair Javaid      if (bp_index == LLDB_INVALID_INDEX32)
435*2441aecdSOmair Javaid          return LLDB_INVALID_INDEX32;
436*2441aecdSOmair Javaid 
437*2441aecdSOmair Javaid     // Add new or update existing watchpoint
438*2441aecdSOmair Javaid     if ((m_hbr_regs[bp_index].control & 1) == 0)
439*2441aecdSOmair Javaid     {
440*2441aecdSOmair Javaid         m_hbr_regs[bp_index].address = addr;
441*2441aecdSOmair Javaid         m_hbr_regs[bp_index].control = control_value;
442*2441aecdSOmair Javaid         m_hbr_regs[bp_index].refcount = 1;
443*2441aecdSOmair Javaid 
444*2441aecdSOmair Javaid         // PTRACE call to set corresponding hardware breakpoint register.
445*2441aecdSOmair Javaid         error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index);
446*2441aecdSOmair Javaid 
447*2441aecdSOmair Javaid         if (error.Fail())
448*2441aecdSOmair Javaid             return LLDB_INVALID_INDEX32;
449*2441aecdSOmair Javaid     }
450*2441aecdSOmair Javaid     else
451*2441aecdSOmair Javaid         m_hbr_regs[bp_index].refcount++;
452*2441aecdSOmair Javaid 
453*2441aecdSOmair Javaid     return bp_index;
454*2441aecdSOmair Javaid }
455*2441aecdSOmair Javaid 
456*2441aecdSOmair Javaid bool
457*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::ClearHardwareBreakpoint (uint32_t hw_idx)
458*2441aecdSOmair Javaid {
459*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
460*2441aecdSOmair Javaid 
461*2441aecdSOmair Javaid     if (log)
462*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
463*2441aecdSOmair Javaid 
464*2441aecdSOmair Javaid     Error error;
465*2441aecdSOmair Javaid 
466*2441aecdSOmair Javaid     // Read hardware breakpoint and watchpoint information.
467*2441aecdSOmair Javaid     error = ReadHardwareDebugInfo ();
468*2441aecdSOmair Javaid 
469*2441aecdSOmair Javaid     if (error.Fail())
470*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
471*2441aecdSOmair Javaid 
472*2441aecdSOmair Javaid     if (hw_idx >= m_max_hbp_supported)
473*2441aecdSOmair Javaid         return false;
474*2441aecdSOmair Javaid 
475*2441aecdSOmair Javaid     // Update reference count if multiple references.
476*2441aecdSOmair Javaid     if (m_hbr_regs[hw_idx].refcount > 1)
477*2441aecdSOmair Javaid     {
478*2441aecdSOmair Javaid         m_hbr_regs[hw_idx].refcount--;
479*2441aecdSOmair Javaid         return true;
480*2441aecdSOmair Javaid     }
481*2441aecdSOmair Javaid     else if (m_hbr_regs[hw_idx].refcount == 1)
482*2441aecdSOmair Javaid     {
483*2441aecdSOmair Javaid         m_hbr_regs[hw_idx].control &= ~1;
484*2441aecdSOmair Javaid         m_hbr_regs[hw_idx].address = 0;
485*2441aecdSOmair Javaid         m_hbr_regs[hw_idx].refcount = 0;
486*2441aecdSOmair Javaid 
487*2441aecdSOmair Javaid         // PTRACE call to clear corresponding hardware breakpoint register.
488*2441aecdSOmair Javaid         WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx);
489*2441aecdSOmair Javaid 
490*2441aecdSOmair Javaid         if (error.Fail())
491*2441aecdSOmair Javaid             return LLDB_INVALID_INDEX32;
492*2441aecdSOmair Javaid 
493*2441aecdSOmair Javaid         return true;
494*2441aecdSOmair Javaid     }
495*2441aecdSOmair Javaid 
496*2441aecdSOmair Javaid     return false;
497*2441aecdSOmair Javaid }
498*2441aecdSOmair Javaid 
499*2441aecdSOmair Javaid uint32_t
500*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints ()
501*2441aecdSOmair Javaid {
502*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
503*2441aecdSOmair Javaid 
504*2441aecdSOmair Javaid     if (log)
505*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
506*2441aecdSOmair Javaid 
507*2441aecdSOmair Javaid     Error error;
508*2441aecdSOmair Javaid 
509*2441aecdSOmair Javaid     // Read hardware breakpoint and watchpoint information.
510*2441aecdSOmair Javaid     error = ReadHardwareDebugInfo ();
511*2441aecdSOmair Javaid 
512*2441aecdSOmair Javaid     if (error.Fail())
513*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
514*2441aecdSOmair Javaid 
515*2441aecdSOmair Javaid     return m_max_hwp_supported;
516*2441aecdSOmair Javaid }
517*2441aecdSOmair Javaid 
518*2441aecdSOmair Javaid uint32_t
519*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags)
520*2441aecdSOmair Javaid {
521*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
522*2441aecdSOmair Javaid 
523*2441aecdSOmair Javaid     if (log)
524*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
525*2441aecdSOmair Javaid 
526*2441aecdSOmair Javaid     Error error;
527*2441aecdSOmair Javaid 
528*2441aecdSOmair Javaid     // Read hardware breakpoint and watchpoint information.
529*2441aecdSOmair Javaid     error = ReadHardwareDebugInfo ();
530*2441aecdSOmair Javaid 
531*2441aecdSOmair Javaid     if (error.Fail())
532*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
533*2441aecdSOmair Javaid 
534*2441aecdSOmair Javaid     uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
535*2441aecdSOmair Javaid 
536*2441aecdSOmair Javaid     // Check if we are setting watchpoint other than read/write/access
537*2441aecdSOmair Javaid     // Also update watchpoint flag to match Arm write-read bit configuration.
538*2441aecdSOmair Javaid     switch (watch_flags)
539*2441aecdSOmair Javaid     {
540*2441aecdSOmair Javaid         case 1:
541*2441aecdSOmair Javaid             watch_flags = 2;
542*2441aecdSOmair Javaid             break;
543*2441aecdSOmair Javaid         case 2:
544*2441aecdSOmair Javaid             watch_flags = 1;
545*2441aecdSOmair Javaid             break;
546*2441aecdSOmair Javaid         case 3:
547*2441aecdSOmair Javaid             break;
548*2441aecdSOmair Javaid         default:
549*2441aecdSOmair Javaid             return LLDB_INVALID_INDEX32;
550*2441aecdSOmair Javaid     }
551*2441aecdSOmair Javaid 
552*2441aecdSOmair Javaid     // Can't watch zero bytes
553*2441aecdSOmair Javaid     // Can't watch more than 4 bytes per WVR/WCR pair
554*2441aecdSOmair Javaid 
555*2441aecdSOmair Javaid     if (size == 0 || size > 4)
556*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
557*2441aecdSOmair Javaid 
558*2441aecdSOmair Javaid     // We can only watch up to four bytes that follow a 4 byte aligned address
559*2441aecdSOmair Javaid     // per watchpoint register pair, so make sure we can properly encode this.
560*2441aecdSOmair Javaid     addr_word_offset = addr % 4;
561*2441aecdSOmair Javaid     byte_mask = ((1u << size) - 1u) << addr_word_offset;
562*2441aecdSOmair Javaid 
563*2441aecdSOmair Javaid     // Check if we need multiple watchpoint register
564*2441aecdSOmair Javaid     if (byte_mask > 0xfu)
565*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
566*2441aecdSOmair Javaid 
567*2441aecdSOmair Javaid     // Setup control value
568*2441aecdSOmair Javaid     // Make the byte_mask into a valid Byte Address Select mask
569*2441aecdSOmair Javaid     control_value = byte_mask << 5;
570*2441aecdSOmair Javaid 
571*2441aecdSOmair Javaid     //Turn on appropriate watchpoint flags read or write
572*2441aecdSOmair Javaid     control_value |= (watch_flags << 3);
573*2441aecdSOmair Javaid 
574*2441aecdSOmair Javaid     // Enable this watchpoint and make it stop in privileged or user mode;
575*2441aecdSOmair Javaid     control_value |= 7;
576*2441aecdSOmair Javaid 
577*2441aecdSOmair Javaid     // Make sure bits 1:0 are clear in our address
578*2441aecdSOmair Javaid     addr &= ~((lldb::addr_t)3);
579*2441aecdSOmair Javaid 
580*2441aecdSOmair Javaid     // Iterate over stored watchpoints
581*2441aecdSOmair Javaid     // Find a free wp_index or update reference count if duplicate.
582*2441aecdSOmair Javaid     wp_index = LLDB_INVALID_INDEX32;
583*2441aecdSOmair Javaid     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
584*2441aecdSOmair Javaid     {
585*2441aecdSOmair Javaid         if ((m_hwp_regs[i].control & 1) == 0)
586*2441aecdSOmair Javaid         {
587*2441aecdSOmair Javaid             wp_index = i; // Mark last free slot
588*2441aecdSOmair Javaid         }
589*2441aecdSOmair Javaid         else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value)
590*2441aecdSOmair Javaid         {
591*2441aecdSOmair Javaid             wp_index = i; // Mark duplicate index
592*2441aecdSOmair Javaid             break; // Stop searching here
593*2441aecdSOmair Javaid         }
594*2441aecdSOmair Javaid     }
595*2441aecdSOmair Javaid 
596*2441aecdSOmair Javaid      if (wp_index == LLDB_INVALID_INDEX32)
597*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
598*2441aecdSOmair Javaid 
599*2441aecdSOmair Javaid     // Add new or update existing watchpoint
600*2441aecdSOmair Javaid     if ((m_hwp_regs[wp_index].control & 1) == 0)
601*2441aecdSOmair Javaid     {
602*2441aecdSOmair Javaid         // Update watchpoint in local cache
603*2441aecdSOmair Javaid         m_hwp_regs[wp_index].address = addr;
604*2441aecdSOmair Javaid         m_hwp_regs[wp_index].control = control_value;
605*2441aecdSOmair Javaid         m_hwp_regs[wp_index].refcount = 1;
606*2441aecdSOmair Javaid 
607*2441aecdSOmair Javaid         // PTRACE call to set corresponding watchpoint register.
608*2441aecdSOmair Javaid         error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
609*2441aecdSOmair Javaid 
610*2441aecdSOmair Javaid         if (error.Fail())
611*2441aecdSOmair Javaid             return LLDB_INVALID_INDEX32;
612*2441aecdSOmair Javaid     }
613*2441aecdSOmair Javaid     else
614*2441aecdSOmair Javaid         m_hwp_regs[wp_index].refcount++;
615*2441aecdSOmair Javaid 
616*2441aecdSOmair Javaid     return wp_index;
617*2441aecdSOmair Javaid }
618*2441aecdSOmair Javaid 
619*2441aecdSOmair Javaid bool
620*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::ClearHardwareWatchpoint (uint32_t wp_index)
621*2441aecdSOmair Javaid {
622*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
623*2441aecdSOmair Javaid 
624*2441aecdSOmair Javaid     if (log)
625*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
626*2441aecdSOmair Javaid 
627*2441aecdSOmair Javaid     Error error;
628*2441aecdSOmair Javaid 
629*2441aecdSOmair Javaid     // Read hardware breakpoint and watchpoint information.
630*2441aecdSOmair Javaid     error = ReadHardwareDebugInfo ();
631*2441aecdSOmair Javaid 
632*2441aecdSOmair Javaid     if (error.Fail())
633*2441aecdSOmair Javaid         return LLDB_INVALID_INDEX32;
634*2441aecdSOmair Javaid 
635*2441aecdSOmair Javaid     if (wp_index >= m_max_hwp_supported)
636*2441aecdSOmair Javaid         return false;
637*2441aecdSOmair Javaid 
638*2441aecdSOmair Javaid     // Update reference count if multiple references.
639*2441aecdSOmair Javaid     if (m_hwp_regs[wp_index].refcount > 1)
640*2441aecdSOmair Javaid     {
641*2441aecdSOmair Javaid         m_hwp_regs[wp_index].refcount--;
642*2441aecdSOmair Javaid         return true;
643*2441aecdSOmair Javaid     }
644*2441aecdSOmair Javaid     else if (m_hwp_regs[wp_index].refcount == 1)
645*2441aecdSOmair Javaid     {
646*2441aecdSOmair Javaid         // Update watchpoint in local cache
647*2441aecdSOmair Javaid         m_hwp_regs[wp_index].control &= ~1;
648*2441aecdSOmair Javaid         m_hwp_regs[wp_index].address = 0;
649*2441aecdSOmair Javaid         m_hwp_regs[wp_index].refcount = 0;
650*2441aecdSOmair Javaid 
651*2441aecdSOmair Javaid         // Ptrace call to update hardware debug registers
652*2441aecdSOmair Javaid         error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
653*2441aecdSOmair Javaid 
654*2441aecdSOmair Javaid         if (error.Fail())
655*2441aecdSOmair Javaid             return false;
656*2441aecdSOmair Javaid 
657*2441aecdSOmair Javaid         return true;
658*2441aecdSOmair Javaid     }
659*2441aecdSOmair Javaid 
660*2441aecdSOmair Javaid     return false;
661*2441aecdSOmair Javaid }
662*2441aecdSOmair Javaid 
663*2441aecdSOmair Javaid Error
664*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints ()
665*2441aecdSOmair Javaid {
666*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
667*2441aecdSOmair Javaid 
668*2441aecdSOmair Javaid     if (log)
669*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
670*2441aecdSOmair Javaid 
671*2441aecdSOmair Javaid     Error error;
672*2441aecdSOmair Javaid 
673*2441aecdSOmair Javaid     // Read hardware breakpoint and watchpoint information.
674*2441aecdSOmair Javaid     error = ReadHardwareDebugInfo ();
675*2441aecdSOmair Javaid 
676*2441aecdSOmair Javaid     if (error.Fail())
677*2441aecdSOmair Javaid         return error;
678*2441aecdSOmair Javaid 
679*2441aecdSOmair Javaid     for (uint32_t i = 0; i < m_max_hwp_supported; i++)
680*2441aecdSOmair Javaid     {
681*2441aecdSOmair Javaid         if (m_hwp_regs[i].control & 0x01)
682*2441aecdSOmair Javaid         {
683*2441aecdSOmair Javaid             // Clear watchpoints in local cache
684*2441aecdSOmair Javaid             m_hwp_regs[i].control &= ~1;
685*2441aecdSOmair Javaid             m_hwp_regs[i].address = 0;
686*2441aecdSOmair Javaid             m_hwp_regs[i].refcount = 0;
687*2441aecdSOmair Javaid 
688*2441aecdSOmair Javaid             // Ptrace call to update hardware debug registers
689*2441aecdSOmair Javaid             error = WriteHardwareDebugRegs(eDREGTypeWATCH, i);
690*2441aecdSOmair Javaid 
691*2441aecdSOmair Javaid             if (error.Fail())
692*2441aecdSOmair Javaid                 return error;
693*2441aecdSOmair Javaid         }
694*2441aecdSOmair Javaid     }
695*2441aecdSOmair Javaid 
696*2441aecdSOmair Javaid     return Error();
697*2441aecdSOmair Javaid }
698*2441aecdSOmair Javaid 
699*2441aecdSOmair Javaid uint32_t
700*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index)
701*2441aecdSOmair Javaid {
702*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
703*2441aecdSOmair Javaid 
704*2441aecdSOmair Javaid     if (log)
705*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
706*2441aecdSOmair Javaid 
707*2441aecdSOmair Javaid     switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f)
708*2441aecdSOmair Javaid     {
709*2441aecdSOmair Javaid         case 0x01:
710*2441aecdSOmair Javaid             return 1;
711*2441aecdSOmair Javaid         case 0x03:
712*2441aecdSOmair Javaid             return 2;
713*2441aecdSOmair Javaid         case 0x07:
714*2441aecdSOmair Javaid             return 3;
715*2441aecdSOmair Javaid         case 0x0f:
716*2441aecdSOmair Javaid             return 4;
717*2441aecdSOmair Javaid         default:
718*2441aecdSOmair Javaid             return 0;
719*2441aecdSOmair Javaid     }
720*2441aecdSOmair Javaid }
721*2441aecdSOmair Javaid bool
722*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index)
723*2441aecdSOmair Javaid {
724*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
725*2441aecdSOmair Javaid 
726*2441aecdSOmair Javaid     if (log)
727*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
728*2441aecdSOmair Javaid 
729*2441aecdSOmair Javaid     if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
730*2441aecdSOmair Javaid         return true;
731*2441aecdSOmair Javaid     else
732*2441aecdSOmair Javaid         return false;
733*2441aecdSOmair Javaid }
734*2441aecdSOmair Javaid 
735*2441aecdSOmair Javaid Error
736*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
737*2441aecdSOmair Javaid {
738*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
739*2441aecdSOmair Javaid 
740*2441aecdSOmair Javaid     if (log)
741*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
742*2441aecdSOmair Javaid 
743*2441aecdSOmair Javaid     uint32_t watch_size;
744*2441aecdSOmair Javaid     lldb::addr_t watch_addr;
745*2441aecdSOmair Javaid 
746*2441aecdSOmair Javaid     for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
747*2441aecdSOmair Javaid     {
748*2441aecdSOmair Javaid         watch_size = GetWatchpointSize (wp_index);
749*2441aecdSOmair Javaid         watch_addr = m_hwp_regs[wp_index].address;
750*2441aecdSOmair Javaid 
751*2441aecdSOmair Javaid         if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
752*2441aecdSOmair Javaid             && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
753*2441aecdSOmair Javaid         {
754*2441aecdSOmair Javaid             return Error();
755*2441aecdSOmair Javaid         }
756*2441aecdSOmair Javaid     }
757*2441aecdSOmair Javaid 
758*2441aecdSOmair Javaid     wp_index = LLDB_INVALID_INDEX32;
759*2441aecdSOmair Javaid     return Error();
760*2441aecdSOmair Javaid }
761*2441aecdSOmair Javaid 
762*2441aecdSOmair Javaid lldb::addr_t
763*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index)
764*2441aecdSOmair Javaid {
765*2441aecdSOmair Javaid     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
766*2441aecdSOmair Javaid 
767*2441aecdSOmair Javaid     if (log)
768*2441aecdSOmair Javaid         log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
769*2441aecdSOmair Javaid 
770*2441aecdSOmair Javaid     if (wp_index >= m_max_hwp_supported)
771*2441aecdSOmair Javaid         return LLDB_INVALID_ADDRESS;
772*2441aecdSOmair Javaid 
773*2441aecdSOmair Javaid     if (WatchpointIsEnabled(wp_index))
774*2441aecdSOmair Javaid         return m_hwp_regs[wp_index].address;
775*2441aecdSOmair Javaid     else
776*2441aecdSOmair Javaid         return LLDB_INVALID_ADDRESS;
777*2441aecdSOmair Javaid }
778*2441aecdSOmair Javaid 
779*2441aecdSOmair Javaid Error
780*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::ReadHardwareDebugInfo()
781*2441aecdSOmair Javaid {
782*2441aecdSOmair Javaid     Error error;
783*2441aecdSOmair Javaid 
784*2441aecdSOmair Javaid     if (!m_refresh_hwdebug_info)
785*2441aecdSOmair Javaid     {
786*2441aecdSOmair Javaid         return Error();
787*2441aecdSOmair Javaid     }
788*2441aecdSOmair Javaid 
789*2441aecdSOmair Javaid     unsigned int cap_val;
790*2441aecdSOmair Javaid 
791*2441aecdSOmair Javaid     error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val, sizeof(unsigned int));
792*2441aecdSOmair Javaid 
793*2441aecdSOmair Javaid     if (error.Fail())
794*2441aecdSOmair Javaid         return error;
795*2441aecdSOmair Javaid 
796*2441aecdSOmair Javaid     m_max_hwp_supported = (cap_val >> 8) & 0xff;
797*2441aecdSOmair Javaid     m_max_hbp_supported = cap_val & 0xff;
798*2441aecdSOmair Javaid     m_refresh_hwdebug_info = false;
799*2441aecdSOmair Javaid 
800*2441aecdSOmair Javaid     return error;
801*2441aecdSOmair Javaid }
802*2441aecdSOmair Javaid 
803*2441aecdSOmair Javaid Error
804*2441aecdSOmair Javaid NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_index)
805*2441aecdSOmair Javaid {
806*2441aecdSOmair Javaid     Error error;
807*2441aecdSOmair Javaid 
808*2441aecdSOmair Javaid     lldb::addr_t *addr_buf;
809*2441aecdSOmair Javaid     uint32_t *ctrl_buf;
810*2441aecdSOmair Javaid 
811*2441aecdSOmair Javaid     if (hwbType == eDREGTypeWATCH)
812*2441aecdSOmair Javaid     {
813*2441aecdSOmair Javaid         addr_buf = &m_hwp_regs[hwb_index].address;
814*2441aecdSOmair Javaid         ctrl_buf = &m_hwp_regs[hwb_index].control;
815*2441aecdSOmair Javaid 
816*2441aecdSOmair Javaid         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
817*2441aecdSOmair Javaid                 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 1),
818*2441aecdSOmair Javaid                 addr_buf, sizeof(unsigned int));
819*2441aecdSOmair Javaid 
820*2441aecdSOmair Javaid         if (error.Fail())
821*2441aecdSOmair Javaid             return error;
822*2441aecdSOmair Javaid 
823*2441aecdSOmair Javaid         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
824*2441aecdSOmair Javaid                 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 2),
825*2441aecdSOmair Javaid                 ctrl_buf, sizeof(unsigned int));
826*2441aecdSOmair Javaid     }
827*2441aecdSOmair Javaid     else
828*2441aecdSOmair Javaid     {
829*2441aecdSOmair Javaid         addr_buf = &m_hwp_regs[hwb_index].address;
830*2441aecdSOmair Javaid         ctrl_buf = &m_hwp_regs[hwb_index].control;
831*2441aecdSOmair Javaid 
832*2441aecdSOmair Javaid         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
833*2441aecdSOmair Javaid                 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 1),
834*2441aecdSOmair Javaid                 addr_buf, sizeof(unsigned int));
835*2441aecdSOmair Javaid 
836*2441aecdSOmair Javaid         if (error.Fail())
837*2441aecdSOmair Javaid             return error;
838*2441aecdSOmair Javaid 
839*2441aecdSOmair Javaid         error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
840*2441aecdSOmair Javaid                 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 2),
841*2441aecdSOmair Javaid                 ctrl_buf, sizeof(unsigned int));
842*2441aecdSOmair Javaid 
843*2441aecdSOmair Javaid     }
844*2441aecdSOmair Javaid 
845*2441aecdSOmair Javaid     return error;
846*2441aecdSOmair Javaid }
847068f8a7eSTamas Berghammer #endif // defined(__arm__)
848