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" 162441aecdSOmair 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 23ce26b7a6STamas Berghammer #ifndef PTRACE_GETVFPREGS 24ce26b7a6STamas Berghammer #define PTRACE_GETVFPREGS 27 25ce26b7a6STamas Berghammer #define PTRACE_SETVFPREGS 28 26ce26b7a6STamas Berghammer #endif 272441aecdSOmair Javaid #ifndef PTRACE_GETHBPREGS 282441aecdSOmair Javaid #define PTRACE_GETHBPREGS 29 292441aecdSOmair Javaid #define PTRACE_SETHBPREGS 30 302441aecdSOmair Javaid #endif 312441aecdSOmair Javaid #if !defined(PTRACE_TYPE_ARG3) 322441aecdSOmair Javaid #define PTRACE_TYPE_ARG3 void * 332441aecdSOmair Javaid #endif 342441aecdSOmair Javaid #if !defined(PTRACE_TYPE_ARG4) 352441aecdSOmair Javaid #define PTRACE_TYPE_ARG4 void * 362441aecdSOmair Javaid #endif 372441aecdSOmair Javaid 383f57216cSOmair Javaid using namespace lldb; 393f57216cSOmair Javaid using namespace lldb_private; 403f57216cSOmair Javaid using namespace lldb_private::process_linux; 413f57216cSOmair Javaid 423f57216cSOmair Javaid // arm general purpose registers. 433f57216cSOmair Javaid static const uint32_t g_gpr_regnums_arm[] = 443f57216cSOmair Javaid { 453f57216cSOmair Javaid gpr_r0_arm, 463f57216cSOmair Javaid gpr_r1_arm, 473f57216cSOmair Javaid gpr_r2_arm, 483f57216cSOmair Javaid gpr_r3_arm, 493f57216cSOmair Javaid gpr_r4_arm, 503f57216cSOmair Javaid gpr_r5_arm, 513f57216cSOmair Javaid gpr_r6_arm, 523f57216cSOmair Javaid gpr_r7_arm, 533f57216cSOmair Javaid gpr_r8_arm, 543f57216cSOmair Javaid gpr_r9_arm, 553f57216cSOmair Javaid gpr_r10_arm, 563f57216cSOmair Javaid gpr_r11_arm, 573f57216cSOmair Javaid gpr_r12_arm, 583f57216cSOmair Javaid gpr_sp_arm, 593f57216cSOmair Javaid gpr_lr_arm, 603f57216cSOmair Javaid gpr_pc_arm, 613f57216cSOmair Javaid gpr_cpsr_arm, 623f57216cSOmair Javaid LLDB_INVALID_REGNUM // register sets need to end with this flag 633f57216cSOmair Javaid }; 643f57216cSOmair Javaid static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \ 653f57216cSOmair Javaid "g_gpr_regnums_arm has wrong number of register infos"); 663f57216cSOmair Javaid 673f57216cSOmair Javaid // arm floating point registers. 683f57216cSOmair Javaid static const uint32_t g_fpu_regnums_arm[] = 693f57216cSOmair Javaid { 703f57216cSOmair Javaid fpu_s0_arm, 713f57216cSOmair Javaid fpu_s1_arm, 723f57216cSOmair Javaid fpu_s2_arm, 733f57216cSOmair Javaid fpu_s3_arm, 743f57216cSOmair Javaid fpu_s4_arm, 753f57216cSOmair Javaid fpu_s5_arm, 763f57216cSOmair Javaid fpu_s6_arm, 773f57216cSOmair Javaid fpu_s7_arm, 783f57216cSOmair Javaid fpu_s8_arm, 793f57216cSOmair Javaid fpu_s9_arm, 803f57216cSOmair Javaid fpu_s10_arm, 813f57216cSOmair Javaid fpu_s11_arm, 823f57216cSOmair Javaid fpu_s12_arm, 833f57216cSOmair Javaid fpu_s13_arm, 843f57216cSOmair Javaid fpu_s14_arm, 853f57216cSOmair Javaid fpu_s15_arm, 863f57216cSOmair Javaid fpu_s16_arm, 873f57216cSOmair Javaid fpu_s17_arm, 883f57216cSOmair Javaid fpu_s18_arm, 893f57216cSOmair Javaid fpu_s19_arm, 903f57216cSOmair Javaid fpu_s20_arm, 913f57216cSOmair Javaid fpu_s21_arm, 923f57216cSOmair Javaid fpu_s22_arm, 933f57216cSOmair Javaid fpu_s23_arm, 943f57216cSOmair Javaid fpu_s24_arm, 953f57216cSOmair Javaid fpu_s25_arm, 963f57216cSOmair Javaid fpu_s26_arm, 973f57216cSOmair Javaid fpu_s27_arm, 983f57216cSOmair Javaid fpu_s28_arm, 993f57216cSOmair Javaid fpu_s29_arm, 1003f57216cSOmair Javaid fpu_s30_arm, 1013f57216cSOmair Javaid fpu_s31_arm, 1023f57216cSOmair Javaid fpu_fpscr_arm, 1033f57216cSOmair Javaid LLDB_INVALID_REGNUM // register sets need to end with this flag 1043f57216cSOmair Javaid }; 1053f57216cSOmair Javaid static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \ 1063f57216cSOmair Javaid "g_fpu_regnums_arm has wrong number of register infos"); 1073f57216cSOmair Javaid 1083f57216cSOmair Javaid namespace { 1093f57216cSOmair Javaid // Number of register sets provided by this context. 1103f57216cSOmair Javaid enum 1113f57216cSOmair Javaid { 1123f57216cSOmair Javaid k_num_register_sets = 2 1133f57216cSOmair Javaid }; 1143f57216cSOmair Javaid } 1153f57216cSOmair Javaid 1163f57216cSOmair Javaid // Register sets for arm. 1173f57216cSOmair Javaid static const RegisterSet 1183f57216cSOmair Javaid g_reg_sets_arm[k_num_register_sets] = 1193f57216cSOmair Javaid { 1203f57216cSOmair Javaid { "General Purpose Registers", "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm }, 1213f57216cSOmair Javaid { "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm } 1223f57216cSOmair Javaid }; 1233f57216cSOmair Javaid 124068f8a7eSTamas Berghammer NativeRegisterContextLinux* 125068f8a7eSTamas Berghammer NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, 1263f57216cSOmair Javaid NativeThreadProtocol &native_thread, 127068f8a7eSTamas Berghammer uint32_t concrete_frame_idx) 1283f57216cSOmair Javaid { 129068f8a7eSTamas Berghammer return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); 130068f8a7eSTamas Berghammer } 131068f8a7eSTamas Berghammer 132068f8a7eSTamas Berghammer NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch, 133068f8a7eSTamas Berghammer NativeThreadProtocol &native_thread, 134068f8a7eSTamas Berghammer uint32_t concrete_frame_idx) : 135068f8a7eSTamas Berghammer NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm(target_arch)) 136068f8a7eSTamas Berghammer { 137068f8a7eSTamas Berghammer switch (target_arch.GetMachine()) 1383f57216cSOmair Javaid { 1393f57216cSOmair Javaid case llvm::Triple::arm: 1403f57216cSOmair Javaid m_reg_info.num_registers = k_num_registers_arm; 1413f57216cSOmair Javaid m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; 1423f57216cSOmair Javaid m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; 1433f57216cSOmair Javaid m_reg_info.last_gpr = k_last_gpr_arm; 1443f57216cSOmair Javaid m_reg_info.first_fpr = k_first_fpr_arm; 1453f57216cSOmair Javaid m_reg_info.last_fpr = k_last_fpr_arm; 1463f57216cSOmair Javaid m_reg_info.first_fpr_v = fpu_s0_arm; 1473f57216cSOmair Javaid m_reg_info.last_fpr_v = fpu_s31_arm; 1483f57216cSOmair Javaid m_reg_info.gpr_flags = gpr_cpsr_arm; 1493f57216cSOmair Javaid break; 1503f57216cSOmair Javaid default: 1513f57216cSOmair Javaid assert(false && "Unhandled target architecture."); 1523f57216cSOmair Javaid break; 1533f57216cSOmair Javaid } 1543f57216cSOmair Javaid 1553f57216cSOmair Javaid ::memset(&m_fpr, 0, sizeof (m_fpr)); 1563f57216cSOmair Javaid ::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm)); 1572441aecdSOmair Javaid ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs)); 1582441aecdSOmair Javaid 1592441aecdSOmair Javaid // 16 is just a maximum value, query hardware for actual watchpoint count 1602441aecdSOmair Javaid m_max_hwp_supported = 16; 1612441aecdSOmair Javaid m_max_hbp_supported = 16; 1622441aecdSOmair Javaid m_refresh_hwdebug_info = true; 1633f57216cSOmair Javaid } 1643f57216cSOmair Javaid 1653f57216cSOmair Javaid uint32_t 1663f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetRegisterSetCount () const 1673f57216cSOmair Javaid { 1683f57216cSOmair Javaid return k_num_register_sets; 1693f57216cSOmair Javaid } 1703f57216cSOmair Javaid 1711f149204STamas Berghammer uint32_t 1721f149204STamas Berghammer NativeRegisterContextLinux_arm::GetUserRegisterCount() const 1731f149204STamas Berghammer { 1741f149204STamas Berghammer uint32_t count = 0; 1751f149204STamas Berghammer for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) 1761f149204STamas Berghammer count += g_reg_sets_arm[set_index].num_registers; 1771f149204STamas Berghammer return count; 1781f149204STamas Berghammer } 1791f149204STamas Berghammer 1803f57216cSOmair Javaid const RegisterSet * 1813f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const 1823f57216cSOmair Javaid { 1833f57216cSOmair Javaid if (set_index < k_num_register_sets) 1843f57216cSOmair Javaid return &g_reg_sets_arm[set_index]; 1853f57216cSOmair Javaid 1863f57216cSOmair Javaid return nullptr; 1873f57216cSOmair Javaid } 1883f57216cSOmair Javaid 1893f57216cSOmair Javaid Error 1903f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 1913f57216cSOmair Javaid { 1923f57216cSOmair Javaid Error error; 1933f57216cSOmair Javaid 1943f57216cSOmair Javaid if (!reg_info) 1953f57216cSOmair Javaid { 1963f57216cSOmair Javaid error.SetErrorString ("reg_info NULL"); 1973f57216cSOmair Javaid return error; 1983f57216cSOmair Javaid } 1993f57216cSOmair Javaid 2003f57216cSOmair Javaid const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 2013f57216cSOmair Javaid 2023f57216cSOmair Javaid if (IsFPR(reg)) 2033f57216cSOmair Javaid { 204068f8a7eSTamas Berghammer error = ReadFPR(); 205068f8a7eSTamas Berghammer if (error.Fail()) 2063f57216cSOmair Javaid return error; 2073f57216cSOmair Javaid } 2083f57216cSOmair Javaid else 2093f57216cSOmair Javaid { 2103f57216cSOmair Javaid uint32_t full_reg = reg; 2113f57216cSOmair Javaid bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 2123f57216cSOmair Javaid 2133f57216cSOmair Javaid if (is_subreg) 2143f57216cSOmair Javaid { 2153f57216cSOmair Javaid // Read the full aligned 64-bit register. 2163f57216cSOmair Javaid full_reg = reg_info->invalidate_regs[0]; 2173f57216cSOmair Javaid } 2183f57216cSOmair Javaid 2193f57216cSOmair Javaid error = ReadRegisterRaw(full_reg, reg_value); 2203f57216cSOmair Javaid 2213f57216cSOmair Javaid if (error.Success ()) 2223f57216cSOmair Javaid { 2233f57216cSOmair Javaid // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 2243f57216cSOmair Javaid if (is_subreg && (reg_info->byte_offset & 0x1)) 2253f57216cSOmair Javaid reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 2263f57216cSOmair Javaid 2273f57216cSOmair Javaid // If our return byte size was greater than the return value reg size, then 2283f57216cSOmair Javaid // use the type specified by reg_info rather than the uint64_t default 2293f57216cSOmair Javaid if (reg_value.GetByteSize() > reg_info->byte_size) 2303f57216cSOmair Javaid reg_value.SetType(reg_info); 2313f57216cSOmair Javaid } 2323f57216cSOmair Javaid return error; 2333f57216cSOmair Javaid } 2343f57216cSOmair Javaid 2353f57216cSOmair Javaid // Get pointer to m_fpr variable and set the data from it. 236c40e7b17STamas Berghammer uint32_t fpr_offset = CalculateFprOffset(reg_info); 237c40e7b17STamas Berghammer assert (fpr_offset < sizeof m_fpr); 238c40e7b17STamas Berghammer uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; 2393f57216cSOmair Javaid switch (reg_info->byte_size) 2403f57216cSOmair Javaid { 2413f57216cSOmair Javaid case 2: 2423f57216cSOmair Javaid reg_value.SetUInt16(*(uint16_t *)src); 2433f57216cSOmair Javaid break; 2443f57216cSOmair Javaid case 4: 2453f57216cSOmair Javaid reg_value.SetUInt32(*(uint32_t *)src); 2463f57216cSOmair Javaid break; 2473f57216cSOmair Javaid case 8: 2483f57216cSOmair Javaid reg_value.SetUInt64(*(uint64_t *)src); 2493f57216cSOmair Javaid break; 2503f57216cSOmair Javaid default: 2513f57216cSOmair Javaid assert(false && "Unhandled data size."); 2523f57216cSOmair Javaid error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); 2533f57216cSOmair Javaid break; 2543f57216cSOmair Javaid } 2553f57216cSOmair Javaid 2563f57216cSOmair Javaid return error; 2573f57216cSOmair Javaid } 2583f57216cSOmair Javaid 2593f57216cSOmair Javaid Error 2603f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 2613f57216cSOmair Javaid { 2623f57216cSOmair Javaid if (!reg_info) 2633f57216cSOmair Javaid return Error ("reg_info NULL"); 2643f57216cSOmair Javaid 2653f57216cSOmair Javaid const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 2663f57216cSOmair Javaid if (reg_index == LLDB_INVALID_REGNUM) 2673f57216cSOmair Javaid return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 2683f57216cSOmair Javaid 2693f57216cSOmair Javaid if (IsGPR(reg_index)) 2703f57216cSOmair Javaid return WriteRegisterRaw(reg_index, reg_value); 2713f57216cSOmair Javaid 2723f57216cSOmair Javaid if (IsFPR(reg_index)) 2733f57216cSOmair Javaid { 2743f57216cSOmair Javaid // Get pointer to m_fpr variable and set the data to it. 275c40e7b17STamas Berghammer uint32_t fpr_offset = CalculateFprOffset(reg_info); 276c40e7b17STamas Berghammer assert (fpr_offset < sizeof m_fpr); 277c40e7b17STamas Berghammer uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; 2783f57216cSOmair Javaid switch (reg_info->byte_size) 2793f57216cSOmair Javaid { 2803f57216cSOmair Javaid case 2: 2813f57216cSOmair Javaid *(uint16_t *)dst = reg_value.GetAsUInt16(); 2823f57216cSOmair Javaid break; 2833f57216cSOmair Javaid case 4: 2843f57216cSOmair Javaid *(uint32_t *)dst = reg_value.GetAsUInt32(); 2853f57216cSOmair Javaid break; 2863f57216cSOmair Javaid case 8: 2873f57216cSOmair Javaid *(uint64_t *)dst = reg_value.GetAsUInt64(); 2883f57216cSOmair Javaid break; 2893f57216cSOmair Javaid default: 2903f57216cSOmair Javaid assert(false && "Unhandled data size."); 2913f57216cSOmair Javaid return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 2923f57216cSOmair Javaid } 2933f57216cSOmair Javaid 294068f8a7eSTamas Berghammer Error error = WriteFPR(); 295068f8a7eSTamas Berghammer if (error.Fail()) 296068f8a7eSTamas Berghammer return error; 2973f57216cSOmair Javaid 2983f57216cSOmair Javaid return Error (); 2993f57216cSOmair Javaid } 3003f57216cSOmair Javaid 3013f57216cSOmair Javaid return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 3023f57216cSOmair Javaid } 3033f57216cSOmair Javaid 3043f57216cSOmair Javaid Error 3053f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 3063f57216cSOmair Javaid { 3073f57216cSOmair Javaid Error error; 3083f57216cSOmair Javaid 3093f57216cSOmair Javaid data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 3103f57216cSOmair Javaid if (!data_sp) 311bef47e49SGreg Clayton return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE); 3123f57216cSOmair Javaid 313068f8a7eSTamas Berghammer error = ReadGPR(); 314068f8a7eSTamas Berghammer if (error.Fail()) 3153f57216cSOmair Javaid return error; 3163f57216cSOmair Javaid 317068f8a7eSTamas Berghammer error = ReadFPR(); 318068f8a7eSTamas Berghammer if (error.Fail()) 3193f57216cSOmair Javaid return error; 3203f57216cSOmair Javaid 3213f57216cSOmair Javaid uint8_t *dst = data_sp->GetBytes (); 3223f57216cSOmair Javaid if (dst == nullptr) 3233f57216cSOmair Javaid { 324bef47e49SGreg Clayton error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE); 3253f57216cSOmair Javaid return error; 3263f57216cSOmair Javaid } 3273f57216cSOmair Javaid 3283f57216cSOmair Javaid ::memcpy (dst, &m_gpr_arm, GetGPRSize()); 3293f57216cSOmair Javaid dst += GetGPRSize(); 3303f57216cSOmair Javaid ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 3313f57216cSOmair Javaid 3323f57216cSOmair Javaid return error; 3333f57216cSOmair Javaid } 3343f57216cSOmair Javaid 3353f57216cSOmair Javaid Error 3363f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 3373f57216cSOmair Javaid { 3383f57216cSOmair Javaid Error error; 3393f57216cSOmair Javaid 3403f57216cSOmair Javaid if (!data_sp) 3413f57216cSOmair Javaid { 3423f57216cSOmair Javaid error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 3433f57216cSOmair Javaid return error; 3443f57216cSOmair Javaid } 3453f57216cSOmair Javaid 3463f57216cSOmair Javaid if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 3473f57216cSOmair Javaid { 348bef47e49SGreg 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 ()); 3493f57216cSOmair Javaid return error; 3503f57216cSOmair Javaid } 3513f57216cSOmair Javaid 3523f57216cSOmair Javaid 3533f57216cSOmair Javaid uint8_t *src = data_sp->GetBytes (); 3543f57216cSOmair Javaid if (src == nullptr) 3553f57216cSOmair Javaid { 3563f57216cSOmair Javaid error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 3573f57216cSOmair Javaid return error; 3583f57216cSOmair Javaid } 3593f57216cSOmair Javaid ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ()); 3603f57216cSOmair Javaid 361068f8a7eSTamas Berghammer error = WriteGPR(); 362068f8a7eSTamas Berghammer if (error.Fail()) 3633f57216cSOmair Javaid return error; 3643f57216cSOmair Javaid 3653f57216cSOmair Javaid src += GetRegisterInfoInterface ().GetGPRSize (); 3663f57216cSOmair Javaid ::memcpy (&m_fpr, src, sizeof(m_fpr)); 3673f57216cSOmair Javaid 368068f8a7eSTamas Berghammer error = WriteFPR(); 3693f57216cSOmair Javaid if (error.Fail()) 3703f57216cSOmair Javaid return error; 3713f57216cSOmair Javaid 3723f57216cSOmair Javaid return error; 3733f57216cSOmair Javaid } 3743f57216cSOmair Javaid 3753f57216cSOmair Javaid bool 3763f57216cSOmair Javaid NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const 3773f57216cSOmair Javaid { 3783f57216cSOmair Javaid return reg <= m_reg_info.last_gpr; // GPR's come first. 3793f57216cSOmair Javaid } 3803f57216cSOmair Javaid 3813f57216cSOmair Javaid bool 3823f57216cSOmair Javaid NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const 3833f57216cSOmair Javaid { 3843f57216cSOmair Javaid return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 3853f57216cSOmair Javaid } 3863f57216cSOmair Javaid 3872441aecdSOmair Javaid uint32_t 3882441aecdSOmair Javaid NativeRegisterContextLinux_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) 3892441aecdSOmair Javaid { 3902441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 3912441aecdSOmair Javaid 3922441aecdSOmair Javaid if (log) 3932441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 3942441aecdSOmair Javaid 3952441aecdSOmair Javaid Error error; 3962441aecdSOmair Javaid 3972441aecdSOmair Javaid // Read hardware breakpoint and watchpoint information. 3982441aecdSOmair Javaid error = ReadHardwareDebugInfo (); 3992441aecdSOmair Javaid 4002441aecdSOmair Javaid if (error.Fail()) 4012441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 4022441aecdSOmair Javaid 4032441aecdSOmair Javaid uint32_t control_value = 0, bp_index = 0; 4042441aecdSOmair Javaid 4052441aecdSOmair Javaid // Check if size has a valid hardware breakpoint length. 4062441aecdSOmair Javaid // Thumb instructions are 2-bytes but we have no way here to determine 4072441aecdSOmair Javaid // if target address is a thumb or arm instruction. 4082441aecdSOmair Javaid // TODO: Add support for setting thumb mode hardware breakpoints 4092441aecdSOmair Javaid if (size != 4 && size != 2) 4102441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 4112441aecdSOmair Javaid 4122441aecdSOmair Javaid // Setup control value 4132441aecdSOmair Javaid // Make the byte_mask into a valid Byte Address Select mask 4142441aecdSOmair Javaid control_value = 0xfu << 5; 4152441aecdSOmair Javaid 4162441aecdSOmair Javaid // Enable this breakpoint and make it stop in privileged or user mode; 4172441aecdSOmair Javaid control_value |= 7; 4182441aecdSOmair Javaid 4192441aecdSOmair Javaid // Make sure bits 1:0 are clear in our address 4202441aecdSOmair Javaid // This should be different once we support thumb here. 4212441aecdSOmair Javaid addr &= ~((lldb::addr_t)3); 4222441aecdSOmair Javaid 4232441aecdSOmair Javaid // Iterate over stored hardware breakpoints 4242441aecdSOmair Javaid // Find a free bp_index or update reference count if duplicate. 4252441aecdSOmair Javaid bp_index = LLDB_INVALID_INDEX32; 4262441aecdSOmair Javaid 4272441aecdSOmair Javaid for (uint32_t i = 0; i < m_max_hbp_supported; i++) 4282441aecdSOmair Javaid { 4292441aecdSOmair Javaid if ((m_hbr_regs[i].control & 1) == 0) 4302441aecdSOmair Javaid { 4312441aecdSOmair Javaid bp_index = i; // Mark last free slot 4322441aecdSOmair Javaid } 4332441aecdSOmair Javaid else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) 4342441aecdSOmair Javaid { 4352441aecdSOmair Javaid bp_index = i; // Mark duplicate index 4362441aecdSOmair Javaid break; // Stop searching here 4372441aecdSOmair Javaid } 4382441aecdSOmair Javaid } 4392441aecdSOmair Javaid 4402441aecdSOmair Javaid if (bp_index == LLDB_INVALID_INDEX32) 4412441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 4422441aecdSOmair Javaid 4434aa984c1SOmair Javaid // Add new or update existing breakpoint 4442441aecdSOmair Javaid if ((m_hbr_regs[bp_index].control & 1) == 0) 4452441aecdSOmair Javaid { 4462441aecdSOmair Javaid m_hbr_regs[bp_index].address = addr; 4472441aecdSOmair Javaid m_hbr_regs[bp_index].control = control_value; 4482441aecdSOmair Javaid m_hbr_regs[bp_index].refcount = 1; 4492441aecdSOmair Javaid 4502441aecdSOmair Javaid // PTRACE call to set corresponding hardware breakpoint register. 4512441aecdSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); 4522441aecdSOmair Javaid 4532441aecdSOmair Javaid if (error.Fail()) 454*d5510d1eSOmair Javaid { 455*d5510d1eSOmair Javaid m_hbr_regs[bp_index].address = 0; 456*d5510d1eSOmair Javaid m_hbr_regs[bp_index].control &= ~1; 457*d5510d1eSOmair Javaid m_hbr_regs[bp_index].refcount = 0; 458*d5510d1eSOmair Javaid 4592441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 4602441aecdSOmair Javaid } 461*d5510d1eSOmair Javaid } 4622441aecdSOmair Javaid else 4632441aecdSOmair Javaid m_hbr_regs[bp_index].refcount++; 4642441aecdSOmair Javaid 4652441aecdSOmair Javaid return bp_index; 4662441aecdSOmair Javaid } 4672441aecdSOmair Javaid 4682441aecdSOmair Javaid bool 4692441aecdSOmair Javaid NativeRegisterContextLinux_arm::ClearHardwareBreakpoint (uint32_t hw_idx) 4702441aecdSOmair Javaid { 4712441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 4722441aecdSOmair Javaid 4732441aecdSOmair Javaid if (log) 4742441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 4752441aecdSOmair Javaid 4762441aecdSOmair Javaid Error error; 4772441aecdSOmair Javaid 4782441aecdSOmair Javaid // Read hardware breakpoint and watchpoint information. 4792441aecdSOmair Javaid error = ReadHardwareDebugInfo (); 4802441aecdSOmair Javaid 4812441aecdSOmair Javaid if (error.Fail()) 4824aa984c1SOmair Javaid return false; 4832441aecdSOmair Javaid 4842441aecdSOmair Javaid if (hw_idx >= m_max_hbp_supported) 4852441aecdSOmair Javaid return false; 4862441aecdSOmair Javaid 4872441aecdSOmair Javaid // Update reference count if multiple references. 4882441aecdSOmair Javaid if (m_hbr_regs[hw_idx].refcount > 1) 4892441aecdSOmair Javaid { 4902441aecdSOmair Javaid m_hbr_regs[hw_idx].refcount--; 4912441aecdSOmair Javaid return true; 4922441aecdSOmair Javaid } 4932441aecdSOmair Javaid else if (m_hbr_regs[hw_idx].refcount == 1) 4942441aecdSOmair Javaid { 495*d5510d1eSOmair Javaid // Create a backup we can revert to in case of failure. 496*d5510d1eSOmair Javaid lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; 497*d5510d1eSOmair Javaid uint32_t tempControl = m_hbr_regs[hw_idx].control; 498*d5510d1eSOmair Javaid uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; 499*d5510d1eSOmair Javaid 5002441aecdSOmair Javaid m_hbr_regs[hw_idx].control &= ~1; 5012441aecdSOmair Javaid m_hbr_regs[hw_idx].address = 0; 5022441aecdSOmair Javaid m_hbr_regs[hw_idx].refcount = 0; 5032441aecdSOmair Javaid 5042441aecdSOmair Javaid // PTRACE call to clear corresponding hardware breakpoint register. 5052441aecdSOmair Javaid WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); 5062441aecdSOmair Javaid 5072441aecdSOmair Javaid if (error.Fail()) 508*d5510d1eSOmair Javaid { 509*d5510d1eSOmair Javaid m_hbr_regs[hw_idx].control = tempControl; 510*d5510d1eSOmair Javaid m_hbr_regs[hw_idx].address = tempAddr; 511*d5510d1eSOmair Javaid m_hbr_regs[hw_idx].refcount = tempRefCount; 512*d5510d1eSOmair Javaid 5134aa984c1SOmair Javaid return false; 514*d5510d1eSOmair Javaid } 5152441aecdSOmair Javaid 5162441aecdSOmair Javaid return true; 5172441aecdSOmair Javaid } 5182441aecdSOmair Javaid 5192441aecdSOmair Javaid return false; 5202441aecdSOmair Javaid } 5212441aecdSOmair Javaid 5222441aecdSOmair Javaid uint32_t 5232441aecdSOmair Javaid NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints () 5242441aecdSOmair Javaid { 5252441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 5262441aecdSOmair Javaid 5272441aecdSOmair Javaid if (log) 5282441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 5292441aecdSOmair Javaid 5302441aecdSOmair Javaid Error error; 5312441aecdSOmair Javaid 5322441aecdSOmair Javaid // Read hardware breakpoint and watchpoint information. 5332441aecdSOmair Javaid error = ReadHardwareDebugInfo (); 5342441aecdSOmair Javaid 5352441aecdSOmair Javaid if (error.Fail()) 5362441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 5372441aecdSOmair Javaid 5382441aecdSOmair Javaid return m_max_hwp_supported; 5392441aecdSOmair Javaid } 5402441aecdSOmair Javaid 5412441aecdSOmair Javaid uint32_t 5422441aecdSOmair Javaid NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) 5432441aecdSOmair Javaid { 5442441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 5452441aecdSOmair Javaid 5462441aecdSOmair Javaid if (log) 5472441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 5482441aecdSOmair Javaid 5492441aecdSOmair Javaid Error error; 5502441aecdSOmair Javaid 5512441aecdSOmair Javaid // Read hardware breakpoint and watchpoint information. 5522441aecdSOmair Javaid error = ReadHardwareDebugInfo (); 5532441aecdSOmair Javaid 5542441aecdSOmair Javaid if (error.Fail()) 5552441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 5562441aecdSOmair Javaid 5572441aecdSOmair Javaid uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0; 5582441aecdSOmair Javaid 5592441aecdSOmair Javaid // Check if we are setting watchpoint other than read/write/access 5602441aecdSOmair Javaid // Also update watchpoint flag to match Arm write-read bit configuration. 5612441aecdSOmair Javaid switch (watch_flags) 5622441aecdSOmair Javaid { 5632441aecdSOmair Javaid case 1: 5642441aecdSOmair Javaid watch_flags = 2; 5652441aecdSOmair Javaid break; 5662441aecdSOmair Javaid case 2: 5672441aecdSOmair Javaid watch_flags = 1; 5682441aecdSOmair Javaid break; 5692441aecdSOmair Javaid case 3: 5702441aecdSOmair Javaid break; 5712441aecdSOmair Javaid default: 5722441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 5732441aecdSOmair Javaid } 5742441aecdSOmair Javaid 5752441aecdSOmair Javaid // Can't watch zero bytes 5762441aecdSOmair Javaid // Can't watch more than 4 bytes per WVR/WCR pair 5772441aecdSOmair Javaid 5782441aecdSOmair Javaid if (size == 0 || size > 4) 5792441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 5802441aecdSOmair Javaid 5812441aecdSOmair Javaid // We can only watch up to four bytes that follow a 4 byte aligned address 5822441aecdSOmair Javaid // per watchpoint register pair, so make sure we can properly encode this. 5832441aecdSOmair Javaid addr_word_offset = addr % 4; 5842441aecdSOmair Javaid byte_mask = ((1u << size) - 1u) << addr_word_offset; 5852441aecdSOmair Javaid 5862441aecdSOmair Javaid // Check if we need multiple watchpoint register 5872441aecdSOmair Javaid if (byte_mask > 0xfu) 5882441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 5892441aecdSOmair Javaid 5902441aecdSOmair Javaid // Setup control value 5912441aecdSOmair Javaid // Make the byte_mask into a valid Byte Address Select mask 5922441aecdSOmair Javaid control_value = byte_mask << 5; 5932441aecdSOmair Javaid 5942441aecdSOmair Javaid //Turn on appropriate watchpoint flags read or write 5952441aecdSOmair Javaid control_value |= (watch_flags << 3); 5962441aecdSOmair Javaid 5972441aecdSOmair Javaid // Enable this watchpoint and make it stop in privileged or user mode; 5982441aecdSOmair Javaid control_value |= 7; 5992441aecdSOmair Javaid 6002441aecdSOmair Javaid // Make sure bits 1:0 are clear in our address 6012441aecdSOmair Javaid addr &= ~((lldb::addr_t)3); 6022441aecdSOmair Javaid 6032441aecdSOmair Javaid // Iterate over stored watchpoints 6042441aecdSOmair Javaid // Find a free wp_index or update reference count if duplicate. 6052441aecdSOmair Javaid wp_index = LLDB_INVALID_INDEX32; 6062441aecdSOmair Javaid for (uint32_t i = 0; i < m_max_hwp_supported; i++) 6072441aecdSOmair Javaid { 6082441aecdSOmair Javaid if ((m_hwp_regs[i].control & 1) == 0) 6092441aecdSOmair Javaid { 6102441aecdSOmair Javaid wp_index = i; // Mark last free slot 6112441aecdSOmair Javaid } 6122441aecdSOmair Javaid else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) 6132441aecdSOmair Javaid { 6142441aecdSOmair Javaid wp_index = i; // Mark duplicate index 6152441aecdSOmair Javaid break; // Stop searching here 6162441aecdSOmair Javaid } 6172441aecdSOmair Javaid } 6182441aecdSOmair Javaid 6192441aecdSOmair Javaid if (wp_index == LLDB_INVALID_INDEX32) 6202441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 6212441aecdSOmair Javaid 6222441aecdSOmair Javaid // Add new or update existing watchpoint 6232441aecdSOmair Javaid if ((m_hwp_regs[wp_index].control & 1) == 0) 6242441aecdSOmair Javaid { 6252441aecdSOmair Javaid // Update watchpoint in local cache 6262441aecdSOmair Javaid m_hwp_regs[wp_index].address = addr; 6272441aecdSOmair Javaid m_hwp_regs[wp_index].control = control_value; 6282441aecdSOmair Javaid m_hwp_regs[wp_index].refcount = 1; 6292441aecdSOmair Javaid 6302441aecdSOmair Javaid // PTRACE call to set corresponding watchpoint register. 6312441aecdSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); 6322441aecdSOmair Javaid 6332441aecdSOmair Javaid if (error.Fail()) 634*d5510d1eSOmair Javaid { 635*d5510d1eSOmair Javaid m_hwp_regs[wp_index].address = 0; 636*d5510d1eSOmair Javaid m_hwp_regs[wp_index].control &= ~1; 637*d5510d1eSOmair Javaid m_hwp_regs[wp_index].refcount = 0; 638*d5510d1eSOmair Javaid 6392441aecdSOmair Javaid return LLDB_INVALID_INDEX32; 6402441aecdSOmair Javaid } 641*d5510d1eSOmair Javaid } 6422441aecdSOmair Javaid else 6432441aecdSOmair Javaid m_hwp_regs[wp_index].refcount++; 6442441aecdSOmair Javaid 6452441aecdSOmair Javaid return wp_index; 6462441aecdSOmair Javaid } 6472441aecdSOmair Javaid 6482441aecdSOmair Javaid bool 6492441aecdSOmair Javaid NativeRegisterContextLinux_arm::ClearHardwareWatchpoint (uint32_t wp_index) 6502441aecdSOmair Javaid { 6512441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 6522441aecdSOmair Javaid 6532441aecdSOmair Javaid if (log) 6542441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 6552441aecdSOmair Javaid 6562441aecdSOmair Javaid Error error; 6572441aecdSOmair Javaid 6582441aecdSOmair Javaid // Read hardware breakpoint and watchpoint information. 6592441aecdSOmair Javaid error = ReadHardwareDebugInfo (); 6602441aecdSOmair Javaid 6612441aecdSOmair Javaid if (error.Fail()) 6624aa984c1SOmair Javaid return false; 6632441aecdSOmair Javaid 6642441aecdSOmair Javaid if (wp_index >= m_max_hwp_supported) 6652441aecdSOmair Javaid return false; 6662441aecdSOmair Javaid 6672441aecdSOmair Javaid // Update reference count if multiple references. 6682441aecdSOmair Javaid if (m_hwp_regs[wp_index].refcount > 1) 6692441aecdSOmair Javaid { 6702441aecdSOmair Javaid m_hwp_regs[wp_index].refcount--; 6712441aecdSOmair Javaid return true; 6722441aecdSOmair Javaid } 6732441aecdSOmair Javaid else if (m_hwp_regs[wp_index].refcount == 1) 6742441aecdSOmair Javaid { 675*d5510d1eSOmair Javaid // Create a backup we can revert to in case of failure. 676*d5510d1eSOmair Javaid lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; 677*d5510d1eSOmair Javaid uint32_t tempControl = m_hwp_regs[wp_index].control; 678*d5510d1eSOmair Javaid uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; 679*d5510d1eSOmair Javaid 6802441aecdSOmair Javaid // Update watchpoint in local cache 6812441aecdSOmair Javaid m_hwp_regs[wp_index].control &= ~1; 6822441aecdSOmair Javaid m_hwp_regs[wp_index].address = 0; 6832441aecdSOmair Javaid m_hwp_regs[wp_index].refcount = 0; 6842441aecdSOmair Javaid 6852441aecdSOmair Javaid // Ptrace call to update hardware debug registers 6862441aecdSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); 6872441aecdSOmair Javaid 6882441aecdSOmair Javaid if (error.Fail()) 689*d5510d1eSOmair Javaid { 690*d5510d1eSOmair Javaid m_hwp_regs[wp_index].control = tempControl; 691*d5510d1eSOmair Javaid m_hwp_regs[wp_index].address = tempAddr; 692*d5510d1eSOmair Javaid m_hwp_regs[wp_index].refcount = tempRefCount; 693*d5510d1eSOmair Javaid 6942441aecdSOmair Javaid return false; 695*d5510d1eSOmair Javaid } 6962441aecdSOmair Javaid 6972441aecdSOmair Javaid return true; 6982441aecdSOmair Javaid } 6992441aecdSOmair Javaid 7002441aecdSOmair Javaid return false; 7012441aecdSOmair Javaid } 7022441aecdSOmair Javaid 7032441aecdSOmair Javaid Error 7042441aecdSOmair Javaid NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints () 7052441aecdSOmair Javaid { 7062441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 7072441aecdSOmair Javaid 7082441aecdSOmair Javaid if (log) 7092441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 7102441aecdSOmair Javaid 7112441aecdSOmair Javaid Error error; 7122441aecdSOmair Javaid 7132441aecdSOmair Javaid // Read hardware breakpoint and watchpoint information. 7142441aecdSOmair Javaid error = ReadHardwareDebugInfo (); 7152441aecdSOmair Javaid 7162441aecdSOmair Javaid if (error.Fail()) 7172441aecdSOmair Javaid return error; 7182441aecdSOmair Javaid 719*d5510d1eSOmair Javaid lldb::addr_t tempAddr = 0; 720*d5510d1eSOmair Javaid uint32_t tempControl = 0, tempRefCount = 0; 721*d5510d1eSOmair Javaid 7222441aecdSOmair Javaid for (uint32_t i = 0; i < m_max_hwp_supported; i++) 7232441aecdSOmair Javaid { 7242441aecdSOmair Javaid if (m_hwp_regs[i].control & 0x01) 7252441aecdSOmair Javaid { 726*d5510d1eSOmair Javaid // Create a backup we can revert to in case of failure. 727*d5510d1eSOmair Javaid tempAddr = m_hwp_regs[i].address; 728*d5510d1eSOmair Javaid tempControl = m_hwp_regs[i].control; 729*d5510d1eSOmair Javaid tempRefCount = m_hwp_regs[i].refcount; 730*d5510d1eSOmair Javaid 7312441aecdSOmair Javaid // Clear watchpoints in local cache 7322441aecdSOmair Javaid m_hwp_regs[i].control &= ~1; 7332441aecdSOmair Javaid m_hwp_regs[i].address = 0; 7342441aecdSOmair Javaid m_hwp_regs[i].refcount = 0; 7352441aecdSOmair Javaid 7362441aecdSOmair Javaid // Ptrace call to update hardware debug registers 7372441aecdSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeWATCH, i); 7382441aecdSOmair Javaid 7392441aecdSOmair Javaid if (error.Fail()) 740*d5510d1eSOmair Javaid { 741*d5510d1eSOmair Javaid m_hwp_regs[i].control = tempControl; 742*d5510d1eSOmair Javaid m_hwp_regs[i].address = tempAddr; 743*d5510d1eSOmair Javaid m_hwp_regs[i].refcount = tempRefCount; 744*d5510d1eSOmair Javaid 7452441aecdSOmair Javaid return error; 7462441aecdSOmair Javaid } 7472441aecdSOmair Javaid } 748*d5510d1eSOmair Javaid } 7492441aecdSOmair Javaid 7502441aecdSOmair Javaid return Error(); 7512441aecdSOmair Javaid } 7522441aecdSOmair Javaid 7532441aecdSOmair Javaid uint32_t 7542441aecdSOmair Javaid NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) 7552441aecdSOmair Javaid { 7562441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 7572441aecdSOmair Javaid 7582441aecdSOmair Javaid if (log) 7592441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 7602441aecdSOmair Javaid 7612441aecdSOmair Javaid switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) 7622441aecdSOmair Javaid { 7632441aecdSOmair Javaid case 0x01: 7642441aecdSOmair Javaid return 1; 7652441aecdSOmair Javaid case 0x03: 7662441aecdSOmair Javaid return 2; 7672441aecdSOmair Javaid case 0x07: 7682441aecdSOmair Javaid return 3; 7692441aecdSOmair Javaid case 0x0f: 7702441aecdSOmair Javaid return 4; 7712441aecdSOmair Javaid default: 7722441aecdSOmair Javaid return 0; 7732441aecdSOmair Javaid } 7742441aecdSOmair Javaid } 7752441aecdSOmair Javaid bool 7762441aecdSOmair Javaid NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) 7772441aecdSOmair Javaid { 7782441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 7792441aecdSOmair Javaid 7802441aecdSOmair Javaid if (log) 7812441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 7822441aecdSOmair Javaid 7832441aecdSOmair Javaid if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 7842441aecdSOmair Javaid return true; 7852441aecdSOmair Javaid else 7862441aecdSOmair Javaid return false; 7872441aecdSOmair Javaid } 7882441aecdSOmair Javaid 7892441aecdSOmair Javaid Error 7902441aecdSOmair Javaid NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) 7912441aecdSOmair Javaid { 7922441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 7932441aecdSOmair Javaid 7942441aecdSOmair Javaid if (log) 7952441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 7962441aecdSOmair Javaid 7972441aecdSOmair Javaid uint32_t watch_size; 7982441aecdSOmair Javaid lldb::addr_t watch_addr; 7992441aecdSOmair Javaid 8002441aecdSOmair Javaid for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) 8012441aecdSOmair Javaid { 8022441aecdSOmair Javaid watch_size = GetWatchpointSize (wp_index); 8032441aecdSOmair Javaid watch_addr = m_hwp_regs[wp_index].address; 8042441aecdSOmair Javaid 8052441aecdSOmair Javaid if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) 8062441aecdSOmair Javaid && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) 8072441aecdSOmair Javaid { 8082441aecdSOmair Javaid return Error(); 8092441aecdSOmair Javaid } 8102441aecdSOmair Javaid } 8112441aecdSOmair Javaid 8122441aecdSOmair Javaid wp_index = LLDB_INVALID_INDEX32; 8132441aecdSOmair Javaid return Error(); 8142441aecdSOmair Javaid } 8152441aecdSOmair Javaid 8162441aecdSOmair Javaid lldb::addr_t 8172441aecdSOmair Javaid NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index) 8182441aecdSOmair Javaid { 8192441aecdSOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 8202441aecdSOmair Javaid 8212441aecdSOmair Javaid if (log) 8222441aecdSOmair Javaid log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 8232441aecdSOmair Javaid 8242441aecdSOmair Javaid if (wp_index >= m_max_hwp_supported) 8252441aecdSOmair Javaid return LLDB_INVALID_ADDRESS; 8262441aecdSOmair Javaid 8272441aecdSOmair Javaid if (WatchpointIsEnabled(wp_index)) 8282441aecdSOmair Javaid return m_hwp_regs[wp_index].address; 8292441aecdSOmair Javaid else 8302441aecdSOmair Javaid return LLDB_INVALID_ADDRESS; 8312441aecdSOmair Javaid } 8322441aecdSOmair Javaid 8332441aecdSOmair Javaid Error 8342441aecdSOmair Javaid NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() 8352441aecdSOmair Javaid { 8362441aecdSOmair Javaid Error error; 8372441aecdSOmair Javaid 8382441aecdSOmair Javaid if (!m_refresh_hwdebug_info) 8392441aecdSOmair Javaid { 8402441aecdSOmair Javaid return Error(); 8412441aecdSOmair Javaid } 8422441aecdSOmair Javaid 8432441aecdSOmair Javaid unsigned int cap_val; 8442441aecdSOmair Javaid 8452441aecdSOmair Javaid error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val, sizeof(unsigned int)); 8462441aecdSOmair Javaid 8472441aecdSOmair Javaid if (error.Fail()) 8482441aecdSOmair Javaid return error; 8492441aecdSOmair Javaid 8502441aecdSOmair Javaid m_max_hwp_supported = (cap_val >> 8) & 0xff; 8512441aecdSOmair Javaid m_max_hbp_supported = cap_val & 0xff; 8522441aecdSOmair Javaid m_refresh_hwdebug_info = false; 8532441aecdSOmair Javaid 8542441aecdSOmair Javaid return error; 8552441aecdSOmair Javaid } 8562441aecdSOmair Javaid 8572441aecdSOmair Javaid Error 8582441aecdSOmair Javaid NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_index) 8592441aecdSOmair Javaid { 8602441aecdSOmair Javaid Error error; 8612441aecdSOmair Javaid 8622441aecdSOmair Javaid lldb::addr_t *addr_buf; 8632441aecdSOmair Javaid uint32_t *ctrl_buf; 8642441aecdSOmair Javaid 8652441aecdSOmair Javaid if (hwbType == eDREGTypeWATCH) 8662441aecdSOmair Javaid { 8672441aecdSOmair Javaid addr_buf = &m_hwp_regs[hwb_index].address; 8682441aecdSOmair Javaid ctrl_buf = &m_hwp_regs[hwb_index].control; 8692441aecdSOmair Javaid 8702441aecdSOmair Javaid error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 8712441aecdSOmair Javaid m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 1), 8722441aecdSOmair Javaid addr_buf, sizeof(unsigned int)); 8732441aecdSOmair Javaid 8742441aecdSOmair Javaid if (error.Fail()) 8752441aecdSOmair Javaid return error; 8762441aecdSOmair Javaid 8772441aecdSOmair Javaid error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 8782441aecdSOmair Javaid m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 2), 8792441aecdSOmair Javaid ctrl_buf, sizeof(unsigned int)); 8802441aecdSOmair Javaid } 8812441aecdSOmair Javaid else 8822441aecdSOmair Javaid { 8832441aecdSOmair Javaid addr_buf = &m_hwp_regs[hwb_index].address; 8842441aecdSOmair Javaid ctrl_buf = &m_hwp_regs[hwb_index].control; 8852441aecdSOmair Javaid 8862441aecdSOmair Javaid error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 8872441aecdSOmair Javaid m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 1), 8882441aecdSOmair Javaid addr_buf, sizeof(unsigned int)); 8892441aecdSOmair Javaid 8902441aecdSOmair Javaid if (error.Fail()) 8912441aecdSOmair Javaid return error; 8922441aecdSOmair Javaid 8932441aecdSOmair Javaid error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 8942441aecdSOmair Javaid m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 2), 8952441aecdSOmair Javaid ctrl_buf, sizeof(unsigned int)); 8962441aecdSOmair Javaid 8972441aecdSOmair Javaid } 8982441aecdSOmair Javaid 8992441aecdSOmair Javaid return error; 9002441aecdSOmair Javaid } 901c40e7b17STamas Berghammer 902c40e7b17STamas Berghammer uint32_t 903c40e7b17STamas Berghammer NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info) const 904c40e7b17STamas Berghammer { 905c40e7b17STamas Berghammer return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; 906c40e7b17STamas Berghammer } 907c40e7b17STamas Berghammer 908ce26b7a6STamas Berghammer Error 909ce26b7a6STamas Berghammer NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset, 910ce26b7a6STamas Berghammer const char* reg_name, 911ce26b7a6STamas Berghammer const RegisterValue &value) 912ce26b7a6STamas Berghammer { 913ce26b7a6STamas Berghammer // PTRACE_POKEUSER don't work in the aarch64 liux kernel used on android devices (always return 914ce26b7a6STamas Berghammer // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR register set, modify 915ce26b7a6STamas Berghammer // the requested register and write it back. This approach is about 4 times slower but the 916ce26b7a6STamas Berghammer // performance overhead is negligible in comparision to processing time in lldb-server. 917ce26b7a6STamas Berghammer assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); 918ce26b7a6STamas Berghammer if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) 919ce26b7a6STamas Berghammer return Error("Register isn't fit into the size of the GPR area"); 920ce26b7a6STamas Berghammer 921ce26b7a6STamas Berghammer Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm)); 922ce26b7a6STamas Berghammer if (error.Fail()) 923ce26b7a6STamas Berghammer return error; 924ce26b7a6STamas Berghammer 925ce26b7a6STamas Berghammer m_gpr_arm[offset / sizeof(uint32_t)] = value.GetAsUInt32(); 926ce26b7a6STamas Berghammer return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm)); 927ce26b7a6STamas Berghammer } 928ce26b7a6STamas Berghammer 929ce26b7a6STamas Berghammer Error 930ce26b7a6STamas Berghammer NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size) 931ce26b7a6STamas Berghammer { 932ce26b7a6STamas Berghammer return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS, 933ce26b7a6STamas Berghammer m_thread.GetID(), 934ce26b7a6STamas Berghammer nullptr, 935ce26b7a6STamas Berghammer buf, 936ce26b7a6STamas Berghammer buf_size); 937ce26b7a6STamas Berghammer } 938ce26b7a6STamas Berghammer 939ce26b7a6STamas Berghammer Error 940ce26b7a6STamas Berghammer NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size) 941ce26b7a6STamas Berghammer { 942ce26b7a6STamas Berghammer return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS, 943ce26b7a6STamas Berghammer m_thread.GetID(), 944ce26b7a6STamas Berghammer nullptr, 945ce26b7a6STamas Berghammer buf, 946ce26b7a6STamas Berghammer buf_size); 947ce26b7a6STamas Berghammer } 948ce26b7a6STamas Berghammer 949068f8a7eSTamas Berghammer #endif // defined(__arm__) 950