11e209fccSTamas Berghammer //===-- NativeRegisterContextLinux_arm64.cpp --------------------*- C++ -*-===// 21e209fccSTamas Berghammer // 31e209fccSTamas Berghammer // The LLVM Compiler Infrastructure 41e209fccSTamas Berghammer // 51e209fccSTamas Berghammer // This file is distributed under the University of Illinois Open Source 61e209fccSTamas Berghammer // License. See LICENSE.TXT for details. 71e209fccSTamas Berghammer // 81e209fccSTamas Berghammer //===----------------------------------------------------------------------===// 91e209fccSTamas Berghammer 10068f8a7eSTamas Berghammer #if defined (__arm64__) || defined (__aarch64__) 11068f8a7eSTamas Berghammer 12e85e6021STamas Berghammer #include "NativeRegisterContextLinux_arm.h" 131e209fccSTamas Berghammer #include "NativeRegisterContextLinux_arm64.h" 141e209fccSTamas Berghammer 15068f8a7eSTamas Berghammer // C Includes 16068f8a7eSTamas Berghammer // C++ Includes 17068f8a7eSTamas Berghammer 18068f8a7eSTamas Berghammer // Other libraries and framework includes 191e209fccSTamas Berghammer #include "lldb/Core/DataBufferHeap.h" 201e209fccSTamas Berghammer #include "lldb/Core/Error.h" 21068f8a7eSTamas Berghammer #include "lldb/Core/Log.h" 221e209fccSTamas Berghammer #include "lldb/Core/RegisterValue.h" 231e209fccSTamas Berghammer #include "lldb/Host/common/NativeProcessProtocol.h" 241e209fccSTamas Berghammer 25068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/NativeProcessLinux.h" 26068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/Procfs.h" 27e85e6021STamas Berghammer #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 28068f8a7eSTamas Berghammer #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" 29068f8a7eSTamas Berghammer 30068f8a7eSTamas Berghammer // System includes - They have to be included after framework includes because they define some 31068f8a7eSTamas Berghammer // macros which collide with variable names in other modules 32068f8a7eSTamas Berghammer #include <sys/socket.h> 33068f8a7eSTamas Berghammer // NT_PRSTATUS and NT_FPREGSET definition 34068f8a7eSTamas Berghammer #include <elf.h> 35dd4799c2SSaleem Abdulrasool // user_hwdebug_state definition 36dd4799c2SSaleem Abdulrasool #include <asm/ptrace.h> 37068f8a7eSTamas Berghammer 38068f8a7eSTamas Berghammer #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) 391e209fccSTamas Berghammer 401e209fccSTamas Berghammer using namespace lldb; 411e209fccSTamas Berghammer using namespace lldb_private; 42db264a6dSTamas Berghammer using namespace lldb_private::process_linux; 431e209fccSTamas Berghammer 441e209fccSTamas Berghammer // ARM64 general purpose registers. 451e209fccSTamas Berghammer static const uint32_t g_gpr_regnums_arm64[] = 461e209fccSTamas Berghammer { 471e209fccSTamas Berghammer gpr_x0_arm64, 481e209fccSTamas Berghammer gpr_x1_arm64, 491e209fccSTamas Berghammer gpr_x2_arm64, 501e209fccSTamas Berghammer gpr_x3_arm64, 511e209fccSTamas Berghammer gpr_x4_arm64, 521e209fccSTamas Berghammer gpr_x5_arm64, 531e209fccSTamas Berghammer gpr_x6_arm64, 541e209fccSTamas Berghammer gpr_x7_arm64, 551e209fccSTamas Berghammer gpr_x8_arm64, 561e209fccSTamas Berghammer gpr_x9_arm64, 571e209fccSTamas Berghammer gpr_x10_arm64, 581e209fccSTamas Berghammer gpr_x11_arm64, 591e209fccSTamas Berghammer gpr_x12_arm64, 601e209fccSTamas Berghammer gpr_x13_arm64, 611e209fccSTamas Berghammer gpr_x14_arm64, 621e209fccSTamas Berghammer gpr_x15_arm64, 631e209fccSTamas Berghammer gpr_x16_arm64, 641e209fccSTamas Berghammer gpr_x17_arm64, 651e209fccSTamas Berghammer gpr_x18_arm64, 661e209fccSTamas Berghammer gpr_x19_arm64, 671e209fccSTamas Berghammer gpr_x20_arm64, 681e209fccSTamas Berghammer gpr_x21_arm64, 691e209fccSTamas Berghammer gpr_x22_arm64, 701e209fccSTamas Berghammer gpr_x23_arm64, 711e209fccSTamas Berghammer gpr_x24_arm64, 721e209fccSTamas Berghammer gpr_x25_arm64, 731e209fccSTamas Berghammer gpr_x26_arm64, 741e209fccSTamas Berghammer gpr_x27_arm64, 751e209fccSTamas Berghammer gpr_x28_arm64, 761e209fccSTamas Berghammer gpr_fp_arm64, 771e209fccSTamas Berghammer gpr_lr_arm64, 781e209fccSTamas Berghammer gpr_sp_arm64, 791e209fccSTamas Berghammer gpr_pc_arm64, 801e209fccSTamas Berghammer gpr_cpsr_arm64, 811e209fccSTamas Berghammer LLDB_INVALID_REGNUM // register sets need to end with this flag 821e209fccSTamas Berghammer }; 831e209fccSTamas Berghammer static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ 841e209fccSTamas Berghammer "g_gpr_regnums_arm64 has wrong number of register infos"); 851e209fccSTamas Berghammer 861e209fccSTamas Berghammer // ARM64 floating point registers. 871e209fccSTamas Berghammer static const uint32_t g_fpu_regnums_arm64[] = 881e209fccSTamas Berghammer { 891e209fccSTamas Berghammer fpu_v0_arm64, 901e209fccSTamas Berghammer fpu_v1_arm64, 911e209fccSTamas Berghammer fpu_v2_arm64, 921e209fccSTamas Berghammer fpu_v3_arm64, 931e209fccSTamas Berghammer fpu_v4_arm64, 941e209fccSTamas Berghammer fpu_v5_arm64, 951e209fccSTamas Berghammer fpu_v6_arm64, 961e209fccSTamas Berghammer fpu_v7_arm64, 971e209fccSTamas Berghammer fpu_v8_arm64, 981e209fccSTamas Berghammer fpu_v9_arm64, 991e209fccSTamas Berghammer fpu_v10_arm64, 1001e209fccSTamas Berghammer fpu_v11_arm64, 1011e209fccSTamas Berghammer fpu_v12_arm64, 1021e209fccSTamas Berghammer fpu_v13_arm64, 1031e209fccSTamas Berghammer fpu_v14_arm64, 1041e209fccSTamas Berghammer fpu_v15_arm64, 1051e209fccSTamas Berghammer fpu_v16_arm64, 1061e209fccSTamas Berghammer fpu_v17_arm64, 1071e209fccSTamas Berghammer fpu_v18_arm64, 1081e209fccSTamas Berghammer fpu_v19_arm64, 1091e209fccSTamas Berghammer fpu_v20_arm64, 1101e209fccSTamas Berghammer fpu_v21_arm64, 1111e209fccSTamas Berghammer fpu_v22_arm64, 1121e209fccSTamas Berghammer fpu_v23_arm64, 1131e209fccSTamas Berghammer fpu_v24_arm64, 1141e209fccSTamas Berghammer fpu_v25_arm64, 1151e209fccSTamas Berghammer fpu_v26_arm64, 1161e209fccSTamas Berghammer fpu_v27_arm64, 1171e209fccSTamas Berghammer fpu_v28_arm64, 1181e209fccSTamas Berghammer fpu_v29_arm64, 1191e209fccSTamas Berghammer fpu_v30_arm64, 1201e209fccSTamas Berghammer fpu_v31_arm64, 1211e209fccSTamas Berghammer fpu_fpsr_arm64, 1221e209fccSTamas Berghammer fpu_fpcr_arm64, 1231e209fccSTamas Berghammer LLDB_INVALID_REGNUM // register sets need to end with this flag 1241e209fccSTamas Berghammer }; 1251e209fccSTamas Berghammer static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ 1261e209fccSTamas Berghammer "g_fpu_regnums_arm64 has wrong number of register infos"); 1271e209fccSTamas Berghammer 1281e209fccSTamas Berghammer namespace { 1291e209fccSTamas Berghammer // Number of register sets provided by this context. 1301e209fccSTamas Berghammer enum 1311e209fccSTamas Berghammer { 1321e209fccSTamas Berghammer k_num_register_sets = 2 1331e209fccSTamas Berghammer }; 1341e209fccSTamas Berghammer } 1351e209fccSTamas Berghammer 1361e209fccSTamas Berghammer // Register sets for ARM64. 137db264a6dSTamas Berghammer static const RegisterSet 1381e209fccSTamas Berghammer g_reg_sets_arm64[k_num_register_sets] = 1391e209fccSTamas Berghammer { 1401e209fccSTamas Berghammer { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, 1411e209fccSTamas Berghammer { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } 1421e209fccSTamas Berghammer }; 1431e209fccSTamas Berghammer 144068f8a7eSTamas Berghammer NativeRegisterContextLinux* 145068f8a7eSTamas Berghammer NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, 146068f8a7eSTamas Berghammer NativeThreadProtocol &native_thread, 147068f8a7eSTamas Berghammer uint32_t concrete_frame_idx) 148068f8a7eSTamas Berghammer { 149e85e6021STamas Berghammer Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS); 150e85e6021STamas Berghammer switch (target_arch.GetMachine()) 151e85e6021STamas Berghammer { 152e85e6021STamas Berghammer case llvm::Triple::arm: 153e85e6021STamas Berghammer return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); 154e85e6021STamas Berghammer case llvm::Triple::aarch64: 155068f8a7eSTamas Berghammer return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); 156e85e6021STamas Berghammer default: 157e85e6021STamas Berghammer if (log) 158e85e6021STamas Berghammer log->Printf("NativeRegisterContextLinux::%s() have no register context for architecture: %s\n", __FUNCTION__, 159e85e6021STamas Berghammer target_arch.GetTriple().getArchName().str().c_str()); 160e85e6021STamas Berghammer return nullptr; 161e85e6021STamas Berghammer } 162068f8a7eSTamas Berghammer } 163068f8a7eSTamas Berghammer 164068f8a7eSTamas Berghammer NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, 165068f8a7eSTamas Berghammer NativeThreadProtocol &native_thread, 166068f8a7eSTamas Berghammer uint32_t concrete_frame_idx) : 167068f8a7eSTamas Berghammer NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch)) 168068f8a7eSTamas Berghammer { 169068f8a7eSTamas Berghammer switch (target_arch.GetMachine()) 1701e209fccSTamas Berghammer { 1711e209fccSTamas Berghammer case llvm::Triple::aarch64: 1721e209fccSTamas Berghammer m_reg_info.num_registers = k_num_registers_arm64; 1731e209fccSTamas Berghammer m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; 1741e209fccSTamas Berghammer m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; 1751e209fccSTamas Berghammer m_reg_info.last_gpr = k_last_gpr_arm64; 1761e209fccSTamas Berghammer m_reg_info.first_fpr = k_first_fpr_arm64; 1771e209fccSTamas Berghammer m_reg_info.last_fpr = k_last_fpr_arm64; 1781e209fccSTamas Berghammer m_reg_info.first_fpr_v = fpu_v0_arm64; 1791e209fccSTamas Berghammer m_reg_info.last_fpr_v = fpu_v31_arm64; 1801e209fccSTamas Berghammer m_reg_info.gpr_flags = gpr_cpsr_arm64; 1811e209fccSTamas Berghammer break; 1821e209fccSTamas Berghammer default: 1831e209fccSTamas Berghammer assert(false && "Unhandled target architecture."); 1841e209fccSTamas Berghammer break; 1851e209fccSTamas Berghammer } 1861e209fccSTamas Berghammer 1871e209fccSTamas Berghammer ::memset(&m_fpr, 0, sizeof (m_fpr)); 1881e209fccSTamas Berghammer ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64)); 189ea8c25a8SOmair Javaid ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs)); 190ea8c25a8SOmair Javaid 191ea8c25a8SOmair Javaid // 16 is just a maximum value, query hardware for actual watchpoint count 192ea8c25a8SOmair Javaid m_max_hwp_supported = 16; 193ea8c25a8SOmair Javaid m_max_hbp_supported = 16; 194ea8c25a8SOmair Javaid m_refresh_hwdebug_info = true; 1951e209fccSTamas Berghammer } 1961e209fccSTamas Berghammer 1971e209fccSTamas Berghammer uint32_t 1981e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::GetRegisterSetCount () const 1991e209fccSTamas Berghammer { 2001e209fccSTamas Berghammer return k_num_register_sets; 2011e209fccSTamas Berghammer } 2021e209fccSTamas Berghammer 203db264a6dSTamas Berghammer const RegisterSet * 2041e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const 2051e209fccSTamas Berghammer { 2061e209fccSTamas Berghammer if (set_index < k_num_register_sets) 2071e209fccSTamas Berghammer return &g_reg_sets_arm64[set_index]; 2081e209fccSTamas Berghammer 2091e209fccSTamas Berghammer return nullptr; 2101e209fccSTamas Berghammer } 2111e209fccSTamas Berghammer 212cec93c35STamas Berghammer uint32_t 213cec93c35STamas Berghammer NativeRegisterContextLinux_arm64::GetUserRegisterCount() const 214cec93c35STamas Berghammer { 215cec93c35STamas Berghammer uint32_t count = 0; 216cec93c35STamas Berghammer for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) 217cec93c35STamas Berghammer count += g_reg_sets_arm64[set_index].num_registers; 218cec93c35STamas Berghammer return count; 219cec93c35STamas Berghammer } 220cec93c35STamas Berghammer 221db264a6dSTamas Berghammer Error 2221e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 2231e209fccSTamas Berghammer { 2241e209fccSTamas Berghammer Error error; 2251e209fccSTamas Berghammer 2261e209fccSTamas Berghammer if (!reg_info) 2271e209fccSTamas Berghammer { 2281e209fccSTamas Berghammer error.SetErrorString ("reg_info NULL"); 2291e209fccSTamas Berghammer return error; 2301e209fccSTamas Berghammer } 2311e209fccSTamas Berghammer 2321e209fccSTamas Berghammer const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 2331e209fccSTamas Berghammer 2341e209fccSTamas Berghammer if (IsFPR(reg)) 2351e209fccSTamas Berghammer { 236068f8a7eSTamas Berghammer error = ReadFPR(); 237068f8a7eSTamas Berghammer if (error.Fail()) 2381e209fccSTamas Berghammer return error; 2391e209fccSTamas Berghammer } 2401e209fccSTamas Berghammer else 2411e209fccSTamas Berghammer { 2421e209fccSTamas Berghammer uint32_t full_reg = reg; 2431e209fccSTamas Berghammer bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 2441e209fccSTamas Berghammer 2451e209fccSTamas Berghammer if (is_subreg) 2461e209fccSTamas Berghammer { 2471e209fccSTamas Berghammer // Read the full aligned 64-bit register. 2481e209fccSTamas Berghammer full_reg = reg_info->invalidate_regs[0]; 2491e209fccSTamas Berghammer } 2501e209fccSTamas Berghammer 2511e209fccSTamas Berghammer error = ReadRegisterRaw(full_reg, reg_value); 2521e209fccSTamas Berghammer 2531e209fccSTamas Berghammer if (error.Success ()) 2541e209fccSTamas Berghammer { 2551e209fccSTamas Berghammer // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 2561e209fccSTamas Berghammer if (is_subreg && (reg_info->byte_offset & 0x1)) 2571e209fccSTamas Berghammer reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 2581e209fccSTamas Berghammer 2591e209fccSTamas Berghammer // If our return byte size was greater than the return value reg size, then 2601e209fccSTamas Berghammer // use the type specified by reg_info rather than the uint64_t default 2611e209fccSTamas Berghammer if (reg_value.GetByteSize() > reg_info->byte_size) 2621e209fccSTamas Berghammer reg_value.SetType(reg_info); 2631e209fccSTamas Berghammer } 2641e209fccSTamas Berghammer return error; 2651e209fccSTamas Berghammer } 2661e209fccSTamas Berghammer 2671e209fccSTamas Berghammer // Get pointer to m_fpr variable and set the data from it. 268c40e7b17STamas Berghammer uint32_t fpr_offset = CalculateFprOffset(reg_info); 269c40e7b17STamas Berghammer assert (fpr_offset < sizeof m_fpr); 270c40e7b17STamas Berghammer uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; 271cec93c35STamas Berghammer reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, eByteOrderLittle, error); 2721e209fccSTamas Berghammer 2731e209fccSTamas Berghammer return error; 2741e209fccSTamas Berghammer } 2751e209fccSTamas Berghammer 276db264a6dSTamas Berghammer Error 2771e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 2781e209fccSTamas Berghammer { 2791e209fccSTamas Berghammer if (!reg_info) 2801e209fccSTamas Berghammer return Error ("reg_info NULL"); 2811e209fccSTamas Berghammer 2821e209fccSTamas Berghammer const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 2831e209fccSTamas Berghammer if (reg_index == LLDB_INVALID_REGNUM) 2841e209fccSTamas Berghammer return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 2851e209fccSTamas Berghammer 2861e209fccSTamas Berghammer if (IsGPR(reg_index)) 2871e209fccSTamas Berghammer return WriteRegisterRaw(reg_index, reg_value); 2881e209fccSTamas Berghammer 2891e209fccSTamas Berghammer if (IsFPR(reg_index)) 2901e209fccSTamas Berghammer { 2911e209fccSTamas Berghammer // Get pointer to m_fpr variable and set the data to it. 292c40e7b17STamas Berghammer uint32_t fpr_offset = CalculateFprOffset(reg_info); 293c40e7b17STamas Berghammer assert (fpr_offset < sizeof m_fpr); 294c40e7b17STamas Berghammer uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; 2951e209fccSTamas Berghammer switch (reg_info->byte_size) 2961e209fccSTamas Berghammer { 2971e209fccSTamas Berghammer case 2: 2981e209fccSTamas Berghammer *(uint16_t *)dst = reg_value.GetAsUInt16(); 2991e209fccSTamas Berghammer break; 3001e209fccSTamas Berghammer case 4: 3011e209fccSTamas Berghammer *(uint32_t *)dst = reg_value.GetAsUInt32(); 3021e209fccSTamas Berghammer break; 3031e209fccSTamas Berghammer case 8: 3041e209fccSTamas Berghammer *(uint64_t *)dst = reg_value.GetAsUInt64(); 3051e209fccSTamas Berghammer break; 3061e209fccSTamas Berghammer default: 3071e209fccSTamas Berghammer assert(false && "Unhandled data size."); 3081e209fccSTamas Berghammer return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 3091e209fccSTamas Berghammer } 3101e209fccSTamas Berghammer 311068f8a7eSTamas Berghammer Error error = WriteFPR(); 312068f8a7eSTamas Berghammer if (error.Fail()) 313068f8a7eSTamas Berghammer return error; 3141e209fccSTamas Berghammer 3151e209fccSTamas Berghammer return Error (); 3161e209fccSTamas Berghammer } 3171e209fccSTamas Berghammer 3181e209fccSTamas Berghammer return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 3191e209fccSTamas Berghammer } 3201e209fccSTamas Berghammer 321db264a6dSTamas Berghammer Error 3221e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 3231e209fccSTamas Berghammer { 3241e209fccSTamas Berghammer Error error; 3251e209fccSTamas Berghammer 326db264a6dSTamas Berghammer data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 3271e209fccSTamas Berghammer if (!data_sp) 3281e209fccSTamas Berghammer return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); 3291e209fccSTamas Berghammer 330068f8a7eSTamas Berghammer error = ReadGPR(); 331068f8a7eSTamas Berghammer if (error.Fail()) 3321e209fccSTamas Berghammer return error; 3331e209fccSTamas Berghammer 334068f8a7eSTamas Berghammer error = ReadFPR(); 335068f8a7eSTamas Berghammer if (error.Fail()) 3361e209fccSTamas Berghammer return error; 3371e209fccSTamas Berghammer 3381e209fccSTamas Berghammer uint8_t *dst = data_sp->GetBytes (); 3391e209fccSTamas Berghammer if (dst == nullptr) 3401e209fccSTamas Berghammer { 3411e209fccSTamas Berghammer error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); 3421e209fccSTamas Berghammer return error; 3431e209fccSTamas Berghammer } 3441e209fccSTamas Berghammer 3451e209fccSTamas Berghammer ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); 3461e209fccSTamas Berghammer dst += GetGPRSize(); 3471e209fccSTamas Berghammer ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 3481e209fccSTamas Berghammer 3491e209fccSTamas Berghammer return error; 3501e209fccSTamas Berghammer } 3511e209fccSTamas Berghammer 352db264a6dSTamas Berghammer Error 3531e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 3541e209fccSTamas Berghammer { 3551e209fccSTamas Berghammer Error error; 3561e209fccSTamas Berghammer 3571e209fccSTamas Berghammer if (!data_sp) 3581e209fccSTamas Berghammer { 3591e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 3601e209fccSTamas Berghammer return error; 3611e209fccSTamas Berghammer } 3621e209fccSTamas Berghammer 3631e209fccSTamas Berghammer if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 3641e209fccSTamas Berghammer { 3651e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); 3661e209fccSTamas Berghammer return error; 3671e209fccSTamas Berghammer } 3681e209fccSTamas Berghammer 3691e209fccSTamas Berghammer 3701e209fccSTamas Berghammer uint8_t *src = data_sp->GetBytes (); 3711e209fccSTamas Berghammer if (src == nullptr) 3721e209fccSTamas Berghammer { 3731e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 3741e209fccSTamas Berghammer return error; 3751e209fccSTamas Berghammer } 3761e209fccSTamas Berghammer ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); 3771e209fccSTamas Berghammer 378068f8a7eSTamas Berghammer error = WriteGPR(); 379068f8a7eSTamas Berghammer if (error.Fail()) 3801e209fccSTamas Berghammer return error; 3811e209fccSTamas Berghammer 3821e209fccSTamas Berghammer src += GetRegisterInfoInterface ().GetGPRSize (); 3831e209fccSTamas Berghammer ::memcpy (&m_fpr, src, sizeof(m_fpr)); 3841e209fccSTamas Berghammer 385068f8a7eSTamas Berghammer error = WriteFPR(); 3861e209fccSTamas Berghammer if (error.Fail()) 3871e209fccSTamas Berghammer return error; 3881e209fccSTamas Berghammer 3891e209fccSTamas Berghammer return error; 3901e209fccSTamas Berghammer } 3911e209fccSTamas Berghammer 3921e209fccSTamas Berghammer bool 3931e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const 3941e209fccSTamas Berghammer { 3951e209fccSTamas Berghammer return reg <= m_reg_info.last_gpr; // GPR's come first. 3961e209fccSTamas Berghammer } 3971e209fccSTamas Berghammer 3981e209fccSTamas Berghammer bool 3991e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const 4001e209fccSTamas Berghammer { 4011e209fccSTamas Berghammer return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 4021e209fccSTamas Berghammer } 4031e209fccSTamas Berghammer 404ea8c25a8SOmair Javaid uint32_t 405ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) 406ea8c25a8SOmair Javaid { 407ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 408ea8c25a8SOmair Javaid 409ea8c25a8SOmair Javaid if (log) 410ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 411ea8c25a8SOmair Javaid 4123a56363aSOmair Javaid Error error; 413ea8c25a8SOmair Javaid 4143a56363aSOmair Javaid // Read hardware breakpoint and watchpoint information. 4153a56363aSOmair Javaid error = ReadHardwareDebugInfo (); 4163a56363aSOmair Javaid 4173a56363aSOmair Javaid if (error.Fail()) 4183a56363aSOmair Javaid return LLDB_INVALID_INDEX32; 4193a56363aSOmair Javaid 4203a56363aSOmair Javaid uint32_t control_value = 0, bp_index = 0; 421ea8c25a8SOmair Javaid 422ea8c25a8SOmair Javaid // Check if size has a valid hardware breakpoint length. 423ea8c25a8SOmair Javaid if (size != 4) 424ea8c25a8SOmair Javaid return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware breakpoint 425ea8c25a8SOmair Javaid 426ea8c25a8SOmair Javaid // Check 4-byte alignment for hardware breakpoint target address. 427ea8c25a8SOmair Javaid if (addr & 0x03) 428ea8c25a8SOmair Javaid return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. 429ea8c25a8SOmair Javaid 430ea8c25a8SOmair Javaid // Setup control value 431ea8c25a8SOmair Javaid control_value = 0; 432ea8c25a8SOmair Javaid control_value |= ((1 << size) - 1) << 5; 433ea8c25a8SOmair Javaid control_value |= (2 << 1) | 1; 434ea8c25a8SOmair Javaid 435ea8c25a8SOmair Javaid // Iterate over stored hardware breakpoints 436ea8c25a8SOmair Javaid // Find a free bp_index or update reference count if duplicate. 437ea8c25a8SOmair Javaid bp_index = LLDB_INVALID_INDEX32; 438ea8c25a8SOmair Javaid for (uint32_t i = 0; i < m_max_hbp_supported; i++) 439ea8c25a8SOmair Javaid { 440ea8c25a8SOmair Javaid if ((m_hbr_regs[i].control & 1) == 0) 441ea8c25a8SOmair Javaid { 442ea8c25a8SOmair Javaid bp_index = i; // Mark last free slot 443ea8c25a8SOmair Javaid } 444ea8c25a8SOmair Javaid else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) 445ea8c25a8SOmair Javaid { 446ea8c25a8SOmair Javaid bp_index = i; // Mark duplicate index 447ea8c25a8SOmair Javaid break; // Stop searching here 448ea8c25a8SOmair Javaid } 449ea8c25a8SOmair Javaid } 450ea8c25a8SOmair Javaid 451ea8c25a8SOmair Javaid if (bp_index == LLDB_INVALID_INDEX32) 452ea8c25a8SOmair Javaid return LLDB_INVALID_INDEX32; 453ea8c25a8SOmair Javaid 454f24741d9SOmair Javaid // Add new or update existing breakpoint 455ea8c25a8SOmair Javaid if ((m_hbr_regs[bp_index].control & 1) == 0) 456ea8c25a8SOmair Javaid { 457ea8c25a8SOmair Javaid m_hbr_regs[bp_index].address = addr; 458ea8c25a8SOmair Javaid m_hbr_regs[bp_index].control = control_value; 459ea8c25a8SOmair Javaid m_hbr_regs[bp_index].refcount = 1; 460ea8c25a8SOmair Javaid 4611fd2a8cfSOmair Javaid // PTRACE call to set corresponding hardware breakpoint register. 4623a56363aSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeBREAK); 4633a56363aSOmair Javaid 4643a56363aSOmair Javaid if (error.Fail()) 465f24741d9SOmair Javaid { 466f24741d9SOmair Javaid m_hbr_regs[bp_index].address = 0; 467f24741d9SOmair Javaid m_hbr_regs[bp_index].control &= ~1; 468f24741d9SOmair Javaid m_hbr_regs[bp_index].refcount = 0; 469f24741d9SOmair Javaid 4703a56363aSOmair Javaid return LLDB_INVALID_INDEX32; 471ea8c25a8SOmair Javaid } 472f24741d9SOmair Javaid } 473ea8c25a8SOmair Javaid else 474ea8c25a8SOmair Javaid m_hbr_regs[bp_index].refcount++; 475ea8c25a8SOmair Javaid 476ea8c25a8SOmair Javaid return bp_index; 477ea8c25a8SOmair Javaid } 478ea8c25a8SOmair Javaid 479ea8c25a8SOmair Javaid bool 480ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx) 481ea8c25a8SOmair Javaid { 482ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 483ea8c25a8SOmair Javaid 484ea8c25a8SOmair Javaid if (log) 485ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 486ea8c25a8SOmair Javaid 4873a56363aSOmair Javaid Error error; 4883a56363aSOmair Javaid 4891fd2a8cfSOmair Javaid // Read hardware breakpoint and watchpoint information. 4903a56363aSOmair Javaid error = ReadHardwareDebugInfo (); 4913a56363aSOmair Javaid 4923a56363aSOmair Javaid if (error.Fail()) 4933a56363aSOmair Javaid return false; 4941fd2a8cfSOmair Javaid 495ea8c25a8SOmair Javaid if (hw_idx >= m_max_hbp_supported) 496ea8c25a8SOmair Javaid return false; 497ea8c25a8SOmair Javaid 498ea8c25a8SOmair Javaid // Update reference count if multiple references. 499ea8c25a8SOmair Javaid if (m_hbr_regs[hw_idx].refcount > 1) 500ea8c25a8SOmair Javaid { 501ea8c25a8SOmair Javaid m_hbr_regs[hw_idx].refcount--; 502ea8c25a8SOmair Javaid return true; 503ea8c25a8SOmair Javaid } 504ea8c25a8SOmair Javaid else if (m_hbr_regs[hw_idx].refcount == 1) 505ea8c25a8SOmair Javaid { 506f24741d9SOmair Javaid // Create a backup we can revert to in case of failure. 507f24741d9SOmair Javaid lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; 508f24741d9SOmair Javaid uint32_t tempControl = m_hbr_regs[hw_idx].control; 509f24741d9SOmair Javaid uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; 510f24741d9SOmair Javaid 511ea8c25a8SOmair Javaid m_hbr_regs[hw_idx].control &= ~1; 512ea8c25a8SOmair Javaid m_hbr_regs[hw_idx].address = 0; 513ea8c25a8SOmair Javaid m_hbr_regs[hw_idx].refcount = 0; 514ea8c25a8SOmair Javaid 5151fd2a8cfSOmair Javaid // PTRACE call to clear corresponding hardware breakpoint register. 5161fd2a8cfSOmair Javaid WriteHardwareDebugRegs(eDREGTypeBREAK); 5173a56363aSOmair Javaid 5183a56363aSOmair Javaid if (error.Fail()) 519f24741d9SOmair Javaid { 520f24741d9SOmair Javaid m_hbr_regs[hw_idx].control = tempControl; 521f24741d9SOmair Javaid m_hbr_regs[hw_idx].address = tempAddr; 522f24741d9SOmair Javaid m_hbr_regs[hw_idx].refcount = tempRefCount; 523f24741d9SOmair Javaid 5243a56363aSOmair Javaid return false; 525f24741d9SOmair Javaid } 5263a56363aSOmair Javaid 5273a56363aSOmair Javaid return true; 528ea8c25a8SOmair Javaid } 529ea8c25a8SOmair Javaid 530ea8c25a8SOmair Javaid return false; 531ea8c25a8SOmair Javaid } 532ea8c25a8SOmair Javaid 533ea8c25a8SOmair Javaid uint32_t 534ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints () 535ea8c25a8SOmair Javaid { 536ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 537ea8c25a8SOmair Javaid 538ea8c25a8SOmair Javaid if (log) 539ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 540ea8c25a8SOmair Javaid 5413a56363aSOmair Javaid Error error; 5423a56363aSOmair Javaid 5431fd2a8cfSOmair Javaid // Read hardware breakpoint and watchpoint information. 5443a56363aSOmair Javaid error = ReadHardwareDebugInfo (); 5453a56363aSOmair Javaid 5463a56363aSOmair Javaid if (error.Fail()) 5473a56363aSOmair Javaid return LLDB_INVALID_INDEX32; 5481fd2a8cfSOmair Javaid 549ea8c25a8SOmair Javaid return m_max_hwp_supported; 550ea8c25a8SOmair Javaid } 551ea8c25a8SOmair Javaid 552ea8c25a8SOmair Javaid uint32_t 553ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) 554ea8c25a8SOmair Javaid { 555ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 556ea8c25a8SOmair Javaid 557ea8c25a8SOmair Javaid if (log) 558ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 559ea8c25a8SOmair Javaid 5603a56363aSOmair Javaid Error error; 561ea8c25a8SOmair Javaid 5623a56363aSOmair Javaid // Read hardware breakpoint and watchpoint information. 5633a56363aSOmair Javaid error = ReadHardwareDebugInfo (); 5643a56363aSOmair Javaid 5653a56363aSOmair Javaid if (error.Fail()) 5663a56363aSOmair Javaid return LLDB_INVALID_INDEX32; 5673a56363aSOmair Javaid 5683a56363aSOmair Javaid uint32_t control_value = 0, wp_index = 0; 569*43507f57SOmair Javaid lldb::addr_t real_addr = addr; 570ea8c25a8SOmair Javaid 5711fd2a8cfSOmair Javaid // Check if we are setting watchpoint other than read/write/access 5721fd2a8cfSOmair Javaid // Also update watchpoint flag to match AArch64 write-read bit configuration. 5731fd2a8cfSOmair Javaid switch (watch_flags) 5741fd2a8cfSOmair Javaid { 5751fd2a8cfSOmair Javaid case 1: 5761fd2a8cfSOmair Javaid watch_flags = 2; 5771fd2a8cfSOmair Javaid break; 5781fd2a8cfSOmair Javaid case 2: 5791fd2a8cfSOmair Javaid watch_flags = 1; 5801fd2a8cfSOmair Javaid break; 5811fd2a8cfSOmair Javaid case 3: 5821fd2a8cfSOmair Javaid break; 5831fd2a8cfSOmair Javaid default: 5841fd2a8cfSOmair Javaid return LLDB_INVALID_INDEX32; 5851fd2a8cfSOmair Javaid } 586ea8c25a8SOmair Javaid 587ea8c25a8SOmair Javaid // Check if size has a valid hardware watchpoint length. 588ea8c25a8SOmair Javaid if (size != 1 && size != 2 && size != 4 && size != 8) 5891fd2a8cfSOmair Javaid return LLDB_INVALID_INDEX32; 590ea8c25a8SOmair Javaid 591ea8c25a8SOmair Javaid // Check 8-byte alignment for hardware watchpoint target address. 592*43507f57SOmair Javaid // Below is a hack to recalculate address and size in order to 593*43507f57SOmair Javaid // make sure we can watch non 8-byte alligned addresses as well. 594ea8c25a8SOmair Javaid if (addr & 0x07) 595*43507f57SOmair Javaid { 596*43507f57SOmair Javaid uint8_t watch_mask = (addr & 0x07) + size; 597*43507f57SOmair Javaid 598*43507f57SOmair Javaid if (watch_mask > 0x08) 5991fd2a8cfSOmair Javaid return LLDB_INVALID_INDEX32; 600*43507f57SOmair Javaid else if (watch_mask <= 0x02) 601*43507f57SOmair Javaid size = 2; 602*43507f57SOmair Javaid else if (watch_mask <= 0x04) 603*43507f57SOmair Javaid size = 4; 604*43507f57SOmair Javaid else 605*43507f57SOmair Javaid size = 8; 606*43507f57SOmair Javaid 607*43507f57SOmair Javaid addr = addr & (~0x07); 608*43507f57SOmair Javaid } 609ea8c25a8SOmair Javaid 610ea8c25a8SOmair Javaid // Setup control value 611ea8c25a8SOmair Javaid control_value = watch_flags << 3; 612ea8c25a8SOmair Javaid control_value |= ((1 << size) - 1) << 5; 613ea8c25a8SOmair Javaid control_value |= (2 << 1) | 1; 614ea8c25a8SOmair Javaid 615ea8c25a8SOmair Javaid // Iterate over stored watchpoints 616ea8c25a8SOmair Javaid // Find a free wp_index or update reference count if duplicate. 617ea8c25a8SOmair Javaid wp_index = LLDB_INVALID_INDEX32; 618ea8c25a8SOmair Javaid for (uint32_t i = 0; i < m_max_hwp_supported; i++) 619ea8c25a8SOmair Javaid { 620ea8c25a8SOmair Javaid if ((m_hwp_regs[i].control & 1) == 0) 621ea8c25a8SOmair Javaid { 622ea8c25a8SOmair Javaid wp_index = i; // Mark last free slot 623ea8c25a8SOmair Javaid } 624ea8c25a8SOmair Javaid else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) 625ea8c25a8SOmair Javaid { 626ea8c25a8SOmair Javaid wp_index = i; // Mark duplicate index 627ea8c25a8SOmair Javaid break; // Stop searching here 628ea8c25a8SOmair Javaid } 629ea8c25a8SOmair Javaid } 630ea8c25a8SOmair Javaid 631ea8c25a8SOmair Javaid if (wp_index == LLDB_INVALID_INDEX32) 632ea8c25a8SOmair Javaid return LLDB_INVALID_INDEX32; 633ea8c25a8SOmair Javaid 634ea8c25a8SOmair Javaid // Add new or update existing watchpoint 635ea8c25a8SOmair Javaid if ((m_hwp_regs[wp_index].control & 1) == 0) 636ea8c25a8SOmair Javaid { 6371fd2a8cfSOmair Javaid // Update watchpoint in local cache 638*43507f57SOmair Javaid m_hwp_regs[wp_index].real_addr = real_addr; 639ea8c25a8SOmair Javaid m_hwp_regs[wp_index].address = addr; 640ea8c25a8SOmair Javaid m_hwp_regs[wp_index].control = control_value; 641ea8c25a8SOmair Javaid m_hwp_regs[wp_index].refcount = 1; 642ea8c25a8SOmair Javaid 643ea8c25a8SOmair Javaid // PTRACE call to set corresponding watchpoint register. 6443a56363aSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeWATCH); 6453a56363aSOmair Javaid 6463a56363aSOmair Javaid if (error.Fail()) 647f24741d9SOmair Javaid { 648f24741d9SOmair Javaid m_hwp_regs[wp_index].address = 0; 649f24741d9SOmair Javaid m_hwp_regs[wp_index].control &= ~1; 650f24741d9SOmair Javaid m_hwp_regs[wp_index].refcount = 0; 651f24741d9SOmair Javaid 6523a56363aSOmair Javaid return LLDB_INVALID_INDEX32; 653ea8c25a8SOmair Javaid } 654f24741d9SOmair Javaid } 655ea8c25a8SOmair Javaid else 656ea8c25a8SOmair Javaid m_hwp_regs[wp_index].refcount++; 657ea8c25a8SOmair Javaid 658ea8c25a8SOmair Javaid return wp_index; 659ea8c25a8SOmair Javaid } 660ea8c25a8SOmair Javaid 661ea8c25a8SOmair Javaid bool 662ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) 663ea8c25a8SOmair Javaid { 664ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 665ea8c25a8SOmair Javaid 666ea8c25a8SOmair Javaid if (log) 667ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 668ea8c25a8SOmair Javaid 6693a56363aSOmair Javaid Error error; 6703a56363aSOmair Javaid 6711fd2a8cfSOmair Javaid // Read hardware breakpoint and watchpoint information. 6723a56363aSOmair Javaid error = ReadHardwareDebugInfo (); 6733a56363aSOmair Javaid 6743a56363aSOmair Javaid if (error.Fail()) 6753a56363aSOmair Javaid return false; 676ea8c25a8SOmair Javaid 677ea8c25a8SOmair Javaid if (wp_index >= m_max_hwp_supported) 678ea8c25a8SOmair Javaid return false; 679ea8c25a8SOmair Javaid 680ea8c25a8SOmair Javaid // Update reference count if multiple references. 681ea8c25a8SOmair Javaid if (m_hwp_regs[wp_index].refcount > 1) 682ea8c25a8SOmair Javaid { 683ea8c25a8SOmair Javaid m_hwp_regs[wp_index].refcount--; 684ea8c25a8SOmair Javaid return true; 685ea8c25a8SOmair Javaid } 686ea8c25a8SOmair Javaid else if (m_hwp_regs[wp_index].refcount == 1) 687ea8c25a8SOmair Javaid { 688f24741d9SOmair Javaid // Create a backup we can revert to in case of failure. 689f24741d9SOmair Javaid lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; 690f24741d9SOmair Javaid uint32_t tempControl = m_hwp_regs[wp_index].control; 691f24741d9SOmair Javaid uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; 692f24741d9SOmair Javaid 6931fd2a8cfSOmair Javaid // Update watchpoint in local cache 694ea8c25a8SOmair Javaid m_hwp_regs[wp_index].control &= ~1; 695ea8c25a8SOmair Javaid m_hwp_regs[wp_index].address = 0; 696ea8c25a8SOmair Javaid m_hwp_regs[wp_index].refcount = 0; 697ea8c25a8SOmair Javaid 6981fd2a8cfSOmair Javaid // Ptrace call to update hardware debug registers 6993a56363aSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeWATCH); 7003a56363aSOmair Javaid 7013a56363aSOmair Javaid if (error.Fail()) 702f24741d9SOmair Javaid { 703f24741d9SOmair Javaid m_hwp_regs[wp_index].control = tempControl; 704f24741d9SOmair Javaid m_hwp_regs[wp_index].address = tempAddr; 705f24741d9SOmair Javaid m_hwp_regs[wp_index].refcount = tempRefCount; 706f24741d9SOmair Javaid 7073a56363aSOmair Javaid return false; 708f24741d9SOmair Javaid } 7093a56363aSOmair Javaid 710ea8c25a8SOmair Javaid return true; 711ea8c25a8SOmair Javaid } 712ea8c25a8SOmair Javaid 713ea8c25a8SOmair Javaid return false; 714ea8c25a8SOmair Javaid } 715ea8c25a8SOmair Javaid 716ea8c25a8SOmair Javaid Error 717ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () 718ea8c25a8SOmair Javaid { 719ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 720ea8c25a8SOmair Javaid 721ea8c25a8SOmair Javaid if (log) 722ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 723ea8c25a8SOmair Javaid 7243a56363aSOmair Javaid Error error; 7253a56363aSOmair Javaid 7261fd2a8cfSOmair Javaid // Read hardware breakpoint and watchpoint information. 7273a56363aSOmair Javaid error = ReadHardwareDebugInfo (); 7283a56363aSOmair Javaid 7293a56363aSOmair Javaid if (error.Fail()) 7303a56363aSOmair Javaid return error; 731ea8c25a8SOmair Javaid 732f24741d9SOmair Javaid lldb::addr_t tempAddr = 0; 733f24741d9SOmair Javaid uint32_t tempControl = 0, tempRefCount = 0; 734f24741d9SOmair Javaid 735ea8c25a8SOmair Javaid for (uint32_t i = 0; i < m_max_hwp_supported; i++) 736ea8c25a8SOmair Javaid { 737ea8c25a8SOmair Javaid if (m_hwp_regs[i].control & 0x01) 738ea8c25a8SOmair Javaid { 739f24741d9SOmair Javaid // Create a backup we can revert to in case of failure. 740f24741d9SOmair Javaid tempAddr = m_hwp_regs[i].address; 741f24741d9SOmair Javaid tempControl = m_hwp_regs[i].control; 742f24741d9SOmair Javaid tempRefCount = m_hwp_regs[i].refcount; 743f24741d9SOmair Javaid 7441fd2a8cfSOmair Javaid // Clear watchpoints in local cache 745ea8c25a8SOmair Javaid m_hwp_regs[i].control &= ~1; 746ea8c25a8SOmair Javaid m_hwp_regs[i].address = 0; 747ea8c25a8SOmair Javaid m_hwp_regs[i].refcount = 0; 748ea8c25a8SOmair Javaid 7491fd2a8cfSOmair Javaid // Ptrace call to update hardware debug registers 7503a56363aSOmair Javaid error = WriteHardwareDebugRegs(eDREGTypeWATCH); 7513a56363aSOmair Javaid 7523a56363aSOmair Javaid if (error.Fail()) 753f24741d9SOmair Javaid { 754f24741d9SOmair Javaid m_hwp_regs[i].control = tempControl; 755f24741d9SOmair Javaid m_hwp_regs[i].address = tempAddr; 756f24741d9SOmair Javaid m_hwp_regs[i].refcount = tempRefCount; 757f24741d9SOmair Javaid 7583a56363aSOmair Javaid return error; 759ea8c25a8SOmair Javaid } 760ea8c25a8SOmair Javaid } 761f24741d9SOmair Javaid } 762ea8c25a8SOmair Javaid 763ea8c25a8SOmair Javaid return Error(); 764ea8c25a8SOmair Javaid } 765ea8c25a8SOmair Javaid 766ea8c25a8SOmair Javaid uint32_t 767ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) 768ea8c25a8SOmair Javaid { 769ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 770ea8c25a8SOmair Javaid 771ea8c25a8SOmair Javaid if (log) 772ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 773ea8c25a8SOmair Javaid switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) 774ea8c25a8SOmair Javaid { 775ea8c25a8SOmair Javaid case 0x01: 776ea8c25a8SOmair Javaid return 1; 777ea8c25a8SOmair Javaid case 0x03: 778ea8c25a8SOmair Javaid return 2; 779ea8c25a8SOmair Javaid case 0x0f: 780ea8c25a8SOmair Javaid return 4; 781ea8c25a8SOmair Javaid case 0xff: 782ea8c25a8SOmair Javaid return 8; 783ea8c25a8SOmair Javaid default: 784ea8c25a8SOmair Javaid return 0; 785ea8c25a8SOmair Javaid } 786ea8c25a8SOmair Javaid } 787ea8c25a8SOmair Javaid bool 788ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) 789ea8c25a8SOmair Javaid { 790ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 791ea8c25a8SOmair Javaid 792ea8c25a8SOmair Javaid if (log) 793ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 794ea8c25a8SOmair Javaid 795ea8c25a8SOmair Javaid if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 796ea8c25a8SOmair Javaid return true; 797ea8c25a8SOmair Javaid else 798ea8c25a8SOmair Javaid return false; 799ea8c25a8SOmair Javaid } 800ea8c25a8SOmair Javaid 801ea8c25a8SOmair Javaid Error 802ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) 803ea8c25a8SOmair Javaid { 804ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 805ea8c25a8SOmair Javaid 806ea8c25a8SOmair Javaid if (log) 807ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 808ea8c25a8SOmair Javaid 809ea8c25a8SOmair Javaid uint32_t watch_size; 810ea8c25a8SOmair Javaid lldb::addr_t watch_addr; 811ea8c25a8SOmair Javaid 812ea8c25a8SOmair Javaid for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) 813ea8c25a8SOmair Javaid { 814ea8c25a8SOmair Javaid watch_size = GetWatchpointSize (wp_index); 815ea8c25a8SOmair Javaid watch_addr = m_hwp_regs[wp_index].address; 816ea8c25a8SOmair Javaid 817ea8c25a8SOmair Javaid if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) 818ea8c25a8SOmair Javaid && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) 819ea8c25a8SOmair Javaid { 820*43507f57SOmair Javaid m_hwp_regs[wp_index].hit_addr = trap_addr; 821ea8c25a8SOmair Javaid return Error(); 822ea8c25a8SOmair Javaid } 823ea8c25a8SOmair Javaid } 824ea8c25a8SOmair Javaid 825ea8c25a8SOmair Javaid wp_index = LLDB_INVALID_INDEX32; 826ea8c25a8SOmair Javaid return Error(); 827ea8c25a8SOmair Javaid } 828ea8c25a8SOmair Javaid 829ea8c25a8SOmair Javaid lldb::addr_t 830ea8c25a8SOmair Javaid NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index) 831ea8c25a8SOmair Javaid { 832ea8c25a8SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 833ea8c25a8SOmair Javaid 834ea8c25a8SOmair Javaid if (log) 835ea8c25a8SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 836ea8c25a8SOmair Javaid 837ea8c25a8SOmair Javaid if (wp_index >= m_max_hwp_supported) 838ea8c25a8SOmair Javaid return LLDB_INVALID_ADDRESS; 839ea8c25a8SOmair Javaid 840ea8c25a8SOmair Javaid if (WatchpointIsEnabled(wp_index)) 841*43507f57SOmair Javaid return m_hwp_regs[wp_index].real_addr; 842*43507f57SOmair Javaid else 843*43507f57SOmair Javaid return LLDB_INVALID_ADDRESS; 844*43507f57SOmair Javaid } 845*43507f57SOmair Javaid 846*43507f57SOmair Javaid lldb::addr_t 847*43507f57SOmair Javaid NativeRegisterContextLinux_arm64::GetWatchpointHitAddress (uint32_t wp_index) 848*43507f57SOmair Javaid { 849*43507f57SOmair Javaid Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 850*43507f57SOmair Javaid 851*43507f57SOmair Javaid if (log) 852*43507f57SOmair Javaid log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 853*43507f57SOmair Javaid 854*43507f57SOmair Javaid if (wp_index >= m_max_hwp_supported) 855*43507f57SOmair Javaid return LLDB_INVALID_ADDRESS; 856*43507f57SOmair Javaid 857*43507f57SOmair Javaid if (WatchpointIsEnabled(wp_index)) 858*43507f57SOmair Javaid return m_hwp_regs[wp_index].hit_addr; 859ea8c25a8SOmair Javaid else 860ea8c25a8SOmair Javaid return LLDB_INVALID_ADDRESS; 861ea8c25a8SOmair Javaid } 862ea8c25a8SOmair Javaid 863068f8a7eSTamas Berghammer Error 8641fd2a8cfSOmair Javaid NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() 865ea8c25a8SOmair Javaid { 8661fd2a8cfSOmair Javaid if (!m_refresh_hwdebug_info) 8671fd2a8cfSOmair Javaid { 8681fd2a8cfSOmair Javaid return Error(); 8691fd2a8cfSOmair Javaid } 8701fd2a8cfSOmair Javaid 871c7512fdcSPavel Labath ::pid_t tid = m_thread.GetID(); 872ea8c25a8SOmair Javaid 873c7512fdcSPavel Labath int regset = NT_ARM_HW_WATCH; 874c7512fdcSPavel Labath struct iovec ioVec; 875c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 876c7512fdcSPavel Labath Error error; 877c7512fdcSPavel Labath 878c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 879c7512fdcSPavel Labath ioVec.iov_len = sizeof (dreg_state); 8804a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); 8813a56363aSOmair Javaid 8823a56363aSOmair Javaid if (error.Fail()) 8833a56363aSOmair Javaid return error; 8843a56363aSOmair Javaid 8851fd2a8cfSOmair Javaid m_max_hwp_supported = dreg_state.dbg_info & 0xff; 886c7512fdcSPavel Labath 887c7512fdcSPavel Labath regset = NT_ARM_HW_BREAK; 8884a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); 8891fd2a8cfSOmair Javaid 8903a56363aSOmair Javaid if (error.Fail()) 8913a56363aSOmair Javaid return error; 8923a56363aSOmair Javaid 8933a56363aSOmair Javaid m_max_hbp_supported = dreg_state.dbg_info & 0xff; 8941fd2a8cfSOmair Javaid m_refresh_hwdebug_info = false; 895c7512fdcSPavel Labath 896c7512fdcSPavel Labath return error; 897ea8c25a8SOmair Javaid } 898068f8a7eSTamas Berghammer 899068f8a7eSTamas Berghammer Error 9001fd2a8cfSOmair Javaid NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) 901068f8a7eSTamas Berghammer { 902c7512fdcSPavel Labath struct iovec ioVec; 903c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 904c7512fdcSPavel Labath Error error; 905c7512fdcSPavel Labath 906c7512fdcSPavel Labath memset (&dreg_state, 0, sizeof (dreg_state)); 907c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 908c7512fdcSPavel Labath 9091fd2a8cfSOmair Javaid if (hwbType == eDREGTypeWATCH) 910c7512fdcSPavel Labath { 9111fd2a8cfSOmair Javaid hwbType = NT_ARM_HW_WATCH; 9125cf948d2SOmair Javaid ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad) 9135cf948d2SOmair Javaid + (sizeof (dreg_state.dbg_regs [0]) * m_max_hwp_supported); 9141fd2a8cfSOmair Javaid 9151fd2a8cfSOmair Javaid for (uint32_t i = 0; i < m_max_hwp_supported; i++) 9161fd2a8cfSOmair Javaid { 9171fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 9181fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 9191fd2a8cfSOmair Javaid } 9201fd2a8cfSOmair Javaid } 9211fd2a8cfSOmair Javaid else 9221fd2a8cfSOmair Javaid { 9231fd2a8cfSOmair Javaid hwbType = NT_ARM_HW_BREAK; 9245cf948d2SOmair Javaid ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad) 9255cf948d2SOmair Javaid + (sizeof (dreg_state.dbg_regs [0]) * m_max_hbp_supported); 9261fd2a8cfSOmair Javaid 9271fd2a8cfSOmair Javaid for (uint32_t i = 0; i < m_max_hbp_supported; i++) 9281fd2a8cfSOmair Javaid { 9291fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address; 9301fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control; 9311fd2a8cfSOmair Javaid } 932068f8a7eSTamas Berghammer } 933068f8a7eSTamas Berghammer 9341fd2a8cfSOmair Javaid return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &hwbType, &ioVec, ioVec.iov_len); 935c7512fdcSPavel Labath } 936c7512fdcSPavel Labath 937c7512fdcSPavel Labath Error 938c7512fdcSPavel Labath NativeRegisterContextLinux_arm64::DoReadRegisterValue(uint32_t offset, 939068f8a7eSTamas Berghammer const char* reg_name, 940068f8a7eSTamas Berghammer uint32_t size, 941068f8a7eSTamas Berghammer RegisterValue &value) 942068f8a7eSTamas Berghammer { 943c7512fdcSPavel Labath Error error; 944c7512fdcSPavel Labath if (offset > sizeof(struct user_pt_regs)) 945c7512fdcSPavel Labath { 946c7512fdcSPavel Labath uintptr_t offset = offset - sizeof(struct user_pt_regs); 947c7512fdcSPavel Labath if (offset > sizeof(struct user_fpsimd_state)) 948c7512fdcSPavel Labath { 949c7512fdcSPavel Labath error.SetErrorString("invalid offset value"); 950c7512fdcSPavel Labath return error; 951c7512fdcSPavel Labath } 952c7512fdcSPavel Labath elf_fpregset_t regs; 953c7512fdcSPavel Labath int regset = NT_FPREGSET; 954c7512fdcSPavel Labath struct iovec ioVec; 955c7512fdcSPavel Labath 956c7512fdcSPavel Labath ioVec.iov_base = ®s; 957c7512fdcSPavel Labath ioVec.iov_len = sizeof regs; 9584a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper( 9594a9babb2SPavel Labath PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); 960c7512fdcSPavel Labath if (error.Success()) 961c7512fdcSPavel Labath { 962c7512fdcSPavel Labath ArchSpec arch; 963c7512fdcSPavel Labath if (m_thread.GetProcess()->GetArchitecture(arch)) 964c7512fdcSPavel Labath value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); 965c7512fdcSPavel Labath else 966c7512fdcSPavel Labath error.SetErrorString("failed to get architecture"); 967c7512fdcSPavel Labath } 968c7512fdcSPavel Labath } 969c7512fdcSPavel Labath else 970c7512fdcSPavel Labath { 971c7512fdcSPavel Labath elf_gregset_t regs; 972c7512fdcSPavel Labath int regset = NT_PRSTATUS; 973c7512fdcSPavel Labath struct iovec ioVec; 974c7512fdcSPavel Labath 975c7512fdcSPavel Labath ioVec.iov_base = ®s; 976c7512fdcSPavel Labath ioVec.iov_len = sizeof regs; 9774a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper( 9784a9babb2SPavel Labath PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); 979c7512fdcSPavel Labath if (error.Success()) 980c7512fdcSPavel Labath { 981c7512fdcSPavel Labath ArchSpec arch; 982c7512fdcSPavel Labath if (m_thread.GetProcess()->GetArchitecture(arch)) 983c7512fdcSPavel Labath value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, arch.GetByteOrder()); 984c7512fdcSPavel Labath else 985c7512fdcSPavel Labath error.SetErrorString("failed to get architecture"); 986c7512fdcSPavel Labath } 987c7512fdcSPavel Labath } 988c7512fdcSPavel Labath return error; 989068f8a7eSTamas Berghammer } 990068f8a7eSTamas Berghammer 991c7512fdcSPavel Labath Error 992c7512fdcSPavel Labath NativeRegisterContextLinux_arm64::DoWriteRegisterValue(uint32_t offset, 993068f8a7eSTamas Berghammer const char* reg_name, 994068f8a7eSTamas Berghammer const RegisterValue &value) 995068f8a7eSTamas Berghammer { 996c7512fdcSPavel Labath Error error; 997c7512fdcSPavel Labath ::pid_t tid = m_thread.GetID(); 998c7512fdcSPavel Labath if (offset > sizeof(struct user_pt_regs)) 999c7512fdcSPavel Labath { 1000c7512fdcSPavel Labath uintptr_t offset = offset - sizeof(struct user_pt_regs); 1001c7512fdcSPavel Labath if (offset > sizeof(struct user_fpsimd_state)) 1002c7512fdcSPavel Labath { 1003c7512fdcSPavel Labath error.SetErrorString("invalid offset value"); 1004c7512fdcSPavel Labath return error; 1005c7512fdcSPavel Labath } 1006c7512fdcSPavel Labath elf_fpregset_t regs; 1007c7512fdcSPavel Labath int regset = NT_FPREGSET; 1008c7512fdcSPavel Labath struct iovec ioVec; 1009c7512fdcSPavel Labath 1010c7512fdcSPavel Labath ioVec.iov_base = ®s; 1011c7512fdcSPavel Labath ioVec.iov_len = sizeof regs; 10124a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); 1013c7512fdcSPavel Labath 1014c7512fdcSPavel Labath if (error.Success()) 1015c7512fdcSPavel Labath { 1016c7512fdcSPavel Labath ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 16); 10174a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); 1018c7512fdcSPavel Labath } 1019c7512fdcSPavel Labath } 1020c7512fdcSPavel Labath else 1021c7512fdcSPavel Labath { 1022c7512fdcSPavel Labath elf_gregset_t regs; 1023c7512fdcSPavel Labath int regset = NT_PRSTATUS; 1024c7512fdcSPavel Labath struct iovec ioVec; 1025c7512fdcSPavel Labath 1026c7512fdcSPavel Labath ioVec.iov_base = ®s; 1027c7512fdcSPavel Labath ioVec.iov_len = sizeof regs; 10284a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); 1029c7512fdcSPavel Labath if (error.Success()) 1030c7512fdcSPavel Labath { 1031c7512fdcSPavel Labath ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 8); 10324a9babb2SPavel Labath error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); 1033c7512fdcSPavel Labath } 1034c7512fdcSPavel Labath } 1035c7512fdcSPavel Labath return error; 1036068f8a7eSTamas Berghammer } 1037068f8a7eSTamas Berghammer 1038c7512fdcSPavel Labath Error 1039c7512fdcSPavel Labath NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size) 1040068f8a7eSTamas Berghammer { 1041c7512fdcSPavel Labath int regset = NT_PRSTATUS; 1042c7512fdcSPavel Labath struct iovec ioVec; 1043c7512fdcSPavel Labath Error error; 1044c7512fdcSPavel Labath 1045c7512fdcSPavel Labath ioVec.iov_base = buf; 1046c7512fdcSPavel Labath ioVec.iov_len = buf_size; 10474a9babb2SPavel Labath return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1048068f8a7eSTamas Berghammer } 1049068f8a7eSTamas Berghammer 1050c7512fdcSPavel Labath Error 1051c7512fdcSPavel Labath NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, size_t buf_size) 1052068f8a7eSTamas Berghammer { 1053c7512fdcSPavel Labath int regset = NT_PRSTATUS; 1054c7512fdcSPavel Labath struct iovec ioVec; 1055c7512fdcSPavel Labath Error error; 1056c7512fdcSPavel Labath 1057c7512fdcSPavel Labath ioVec.iov_base = buf; 1058c7512fdcSPavel Labath ioVec.iov_len = buf_size; 10594a9babb2SPavel Labath return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1060068f8a7eSTamas Berghammer } 1061068f8a7eSTamas Berghammer 1062c7512fdcSPavel Labath Error 1063c7512fdcSPavel Labath NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size) 1064068f8a7eSTamas Berghammer { 1065c7512fdcSPavel Labath int regset = NT_FPREGSET; 1066c7512fdcSPavel Labath struct iovec ioVec; 1067c7512fdcSPavel Labath Error error; 1068c7512fdcSPavel Labath 1069c7512fdcSPavel Labath ioVec.iov_base = buf; 1070c7512fdcSPavel Labath ioVec.iov_len = buf_size; 10714a9babb2SPavel Labath return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1072068f8a7eSTamas Berghammer } 1073068f8a7eSTamas Berghammer 1074c7512fdcSPavel Labath Error 1075c7512fdcSPavel Labath NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, size_t buf_size) 1076068f8a7eSTamas Berghammer { 1077c7512fdcSPavel Labath int regset = NT_FPREGSET; 1078c7512fdcSPavel Labath struct iovec ioVec; 1079c7512fdcSPavel Labath Error error; 1080c7512fdcSPavel Labath 1081c7512fdcSPavel Labath ioVec.iov_base = buf; 1082c7512fdcSPavel Labath ioVec.iov_len = buf_size; 10834a9babb2SPavel Labath return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1084068f8a7eSTamas Berghammer } 1085068f8a7eSTamas Berghammer 1086c40e7b17STamas Berghammer uint32_t 1087c40e7b17STamas Berghammer NativeRegisterContextLinux_arm64::CalculateFprOffset(const RegisterInfo* reg_info) const 1088c40e7b17STamas Berghammer { 1089c40e7b17STamas Berghammer return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; 1090c40e7b17STamas Berghammer } 1091c40e7b17STamas Berghammer 1092068f8a7eSTamas Berghammer #endif // defined (__arm64__) || defined (__aarch64__) 1093