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 ®_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 ®_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