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 101e209fccSTamas Berghammer #include "NativeRegisterContextLinux_arm64.h" 111e209fccSTamas Berghammer 121e209fccSTamas Berghammer #include "lldb/lldb-private-forward.h" 131e209fccSTamas Berghammer #include "lldb/Core/DataBufferHeap.h" 141e209fccSTamas Berghammer #include "lldb/Core/Error.h" 151e209fccSTamas Berghammer #include "lldb/Core/RegisterValue.h" 161e209fccSTamas Berghammer #include "lldb/Host/common/NativeProcessProtocol.h" 171e209fccSTamas Berghammer #include "lldb/Host/common/NativeThreadProtocol.h" 181e209fccSTamas Berghammer #include "Plugins/Process/Linux/NativeProcessLinux.h" 191e209fccSTamas Berghammer 201e209fccSTamas Berghammer #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr)) 211e209fccSTamas Berghammer 221e209fccSTamas Berghammer using namespace lldb; 231e209fccSTamas Berghammer using namespace lldb_private; 24*db264a6dSTamas Berghammer using namespace lldb_private::process_linux; 251e209fccSTamas Berghammer 261e209fccSTamas Berghammer // ARM64 general purpose registers. 271e209fccSTamas Berghammer static const uint32_t g_gpr_regnums_arm64[] = 281e209fccSTamas Berghammer { 291e209fccSTamas Berghammer gpr_x0_arm64, 301e209fccSTamas Berghammer gpr_x1_arm64, 311e209fccSTamas Berghammer gpr_x2_arm64, 321e209fccSTamas Berghammer gpr_x3_arm64, 331e209fccSTamas Berghammer gpr_x4_arm64, 341e209fccSTamas Berghammer gpr_x5_arm64, 351e209fccSTamas Berghammer gpr_x6_arm64, 361e209fccSTamas Berghammer gpr_x7_arm64, 371e209fccSTamas Berghammer gpr_x8_arm64, 381e209fccSTamas Berghammer gpr_x9_arm64, 391e209fccSTamas Berghammer gpr_x10_arm64, 401e209fccSTamas Berghammer gpr_x11_arm64, 411e209fccSTamas Berghammer gpr_x12_arm64, 421e209fccSTamas Berghammer gpr_x13_arm64, 431e209fccSTamas Berghammer gpr_x14_arm64, 441e209fccSTamas Berghammer gpr_x15_arm64, 451e209fccSTamas Berghammer gpr_x16_arm64, 461e209fccSTamas Berghammer gpr_x17_arm64, 471e209fccSTamas Berghammer gpr_x18_arm64, 481e209fccSTamas Berghammer gpr_x19_arm64, 491e209fccSTamas Berghammer gpr_x20_arm64, 501e209fccSTamas Berghammer gpr_x21_arm64, 511e209fccSTamas Berghammer gpr_x22_arm64, 521e209fccSTamas Berghammer gpr_x23_arm64, 531e209fccSTamas Berghammer gpr_x24_arm64, 541e209fccSTamas Berghammer gpr_x25_arm64, 551e209fccSTamas Berghammer gpr_x26_arm64, 561e209fccSTamas Berghammer gpr_x27_arm64, 571e209fccSTamas Berghammer gpr_x28_arm64, 581e209fccSTamas Berghammer gpr_fp_arm64, 591e209fccSTamas Berghammer gpr_lr_arm64, 601e209fccSTamas Berghammer gpr_sp_arm64, 611e209fccSTamas Berghammer gpr_pc_arm64, 621e209fccSTamas Berghammer gpr_cpsr_arm64, 631e209fccSTamas Berghammer LLDB_INVALID_REGNUM // register sets need to end with this flag 641e209fccSTamas Berghammer }; 651e209fccSTamas Berghammer static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ 661e209fccSTamas Berghammer "g_gpr_regnums_arm64 has wrong number of register infos"); 671e209fccSTamas Berghammer 681e209fccSTamas Berghammer // ARM64 floating point registers. 691e209fccSTamas Berghammer static const uint32_t g_fpu_regnums_arm64[] = 701e209fccSTamas Berghammer { 711e209fccSTamas Berghammer fpu_v0_arm64, 721e209fccSTamas Berghammer fpu_v1_arm64, 731e209fccSTamas Berghammer fpu_v2_arm64, 741e209fccSTamas Berghammer fpu_v3_arm64, 751e209fccSTamas Berghammer fpu_v4_arm64, 761e209fccSTamas Berghammer fpu_v5_arm64, 771e209fccSTamas Berghammer fpu_v6_arm64, 781e209fccSTamas Berghammer fpu_v7_arm64, 791e209fccSTamas Berghammer fpu_v8_arm64, 801e209fccSTamas Berghammer fpu_v9_arm64, 811e209fccSTamas Berghammer fpu_v10_arm64, 821e209fccSTamas Berghammer fpu_v11_arm64, 831e209fccSTamas Berghammer fpu_v12_arm64, 841e209fccSTamas Berghammer fpu_v13_arm64, 851e209fccSTamas Berghammer fpu_v14_arm64, 861e209fccSTamas Berghammer fpu_v15_arm64, 871e209fccSTamas Berghammer fpu_v16_arm64, 881e209fccSTamas Berghammer fpu_v17_arm64, 891e209fccSTamas Berghammer fpu_v18_arm64, 901e209fccSTamas Berghammer fpu_v19_arm64, 911e209fccSTamas Berghammer fpu_v20_arm64, 921e209fccSTamas Berghammer fpu_v21_arm64, 931e209fccSTamas Berghammer fpu_v22_arm64, 941e209fccSTamas Berghammer fpu_v23_arm64, 951e209fccSTamas Berghammer fpu_v24_arm64, 961e209fccSTamas Berghammer fpu_v25_arm64, 971e209fccSTamas Berghammer fpu_v26_arm64, 981e209fccSTamas Berghammer fpu_v27_arm64, 991e209fccSTamas Berghammer fpu_v28_arm64, 1001e209fccSTamas Berghammer fpu_v29_arm64, 1011e209fccSTamas Berghammer fpu_v30_arm64, 1021e209fccSTamas Berghammer fpu_v31_arm64, 1031e209fccSTamas Berghammer fpu_fpsr_arm64, 1041e209fccSTamas Berghammer fpu_fpcr_arm64, 1051e209fccSTamas Berghammer LLDB_INVALID_REGNUM // register sets need to end with this flag 1061e209fccSTamas Berghammer }; 1071e209fccSTamas Berghammer static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ 1081e209fccSTamas Berghammer "g_fpu_regnums_arm64 has wrong number of register infos"); 1091e209fccSTamas Berghammer 1101e209fccSTamas Berghammer namespace { 1111e209fccSTamas Berghammer // Number of register sets provided by this context. 1121e209fccSTamas Berghammer enum 1131e209fccSTamas Berghammer { 1141e209fccSTamas Berghammer k_num_register_sets = 2 1151e209fccSTamas Berghammer }; 1161e209fccSTamas Berghammer } 1171e209fccSTamas Berghammer 1181e209fccSTamas Berghammer // Register sets for ARM64. 119*db264a6dSTamas Berghammer static const RegisterSet 1201e209fccSTamas Berghammer g_reg_sets_arm64[k_num_register_sets] = 1211e209fccSTamas Berghammer { 1221e209fccSTamas Berghammer { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, 1231e209fccSTamas Berghammer { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } 1241e209fccSTamas Berghammer }; 1251e209fccSTamas Berghammer 1261e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 ( 1271e209fccSTamas Berghammer NativeThreadProtocol &native_thread, 1281e209fccSTamas Berghammer uint32_t concrete_frame_idx, 1291e209fccSTamas Berghammer RegisterInfoInterface *reg_info_interface_p) : 1301e209fccSTamas Berghammer NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p) 1311e209fccSTamas Berghammer { 1321e209fccSTamas Berghammer switch (reg_info_interface_p->m_target_arch.GetMachine()) 1331e209fccSTamas Berghammer { 1341e209fccSTamas Berghammer case llvm::Triple::aarch64: 1351e209fccSTamas Berghammer m_reg_info.num_registers = k_num_registers_arm64; 1361e209fccSTamas Berghammer m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; 1371e209fccSTamas Berghammer m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; 1381e209fccSTamas Berghammer m_reg_info.last_gpr = k_last_gpr_arm64; 1391e209fccSTamas Berghammer m_reg_info.first_fpr = k_first_fpr_arm64; 1401e209fccSTamas Berghammer m_reg_info.last_fpr = k_last_fpr_arm64; 1411e209fccSTamas Berghammer m_reg_info.first_fpr_v = fpu_v0_arm64; 1421e209fccSTamas Berghammer m_reg_info.last_fpr_v = fpu_v31_arm64; 1431e209fccSTamas Berghammer m_reg_info.gpr_flags = gpr_cpsr_arm64; 1441e209fccSTamas Berghammer break; 1451e209fccSTamas Berghammer default: 1461e209fccSTamas Berghammer assert(false && "Unhandled target architecture."); 1471e209fccSTamas Berghammer break; 1481e209fccSTamas Berghammer } 1491e209fccSTamas Berghammer 1501e209fccSTamas Berghammer ::memset(&m_fpr, 0, sizeof (m_fpr)); 1511e209fccSTamas Berghammer ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64)); 1521e209fccSTamas Berghammer } 1531e209fccSTamas Berghammer 1541e209fccSTamas Berghammer uint32_t 1551e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::GetRegisterSetCount () const 1561e209fccSTamas Berghammer { 1571e209fccSTamas Berghammer return k_num_register_sets; 1581e209fccSTamas Berghammer } 1591e209fccSTamas Berghammer 160*db264a6dSTamas Berghammer const RegisterSet * 1611e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const 1621e209fccSTamas Berghammer { 1631e209fccSTamas Berghammer if (set_index < k_num_register_sets) 1641e209fccSTamas Berghammer return &g_reg_sets_arm64[set_index]; 1651e209fccSTamas Berghammer 1661e209fccSTamas Berghammer return nullptr; 1671e209fccSTamas Berghammer } 1681e209fccSTamas Berghammer 169*db264a6dSTamas Berghammer Error 1701e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 1711e209fccSTamas Berghammer { 1721e209fccSTamas Berghammer Error error; 1731e209fccSTamas Berghammer 1741e209fccSTamas Berghammer if (!reg_info) 1751e209fccSTamas Berghammer { 1761e209fccSTamas Berghammer error.SetErrorString ("reg_info NULL"); 1771e209fccSTamas Berghammer return error; 1781e209fccSTamas Berghammer } 1791e209fccSTamas Berghammer 1801e209fccSTamas Berghammer const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 1811e209fccSTamas Berghammer 1821e209fccSTamas Berghammer if (IsFPR(reg)) 1831e209fccSTamas Berghammer { 1841e209fccSTamas Berghammer if (!ReadFPR()) 1851e209fccSTamas Berghammer { 1861e209fccSTamas Berghammer error.SetErrorString ("failed to read floating point register"); 1871e209fccSTamas Berghammer return error; 1881e209fccSTamas Berghammer } 1891e209fccSTamas Berghammer } 1901e209fccSTamas Berghammer else 1911e209fccSTamas Berghammer { 1921e209fccSTamas Berghammer uint32_t full_reg = reg; 1931e209fccSTamas Berghammer bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 1941e209fccSTamas Berghammer 1951e209fccSTamas Berghammer if (is_subreg) 1961e209fccSTamas Berghammer { 1971e209fccSTamas Berghammer // Read the full aligned 64-bit register. 1981e209fccSTamas Berghammer full_reg = reg_info->invalidate_regs[0]; 1991e209fccSTamas Berghammer } 2001e209fccSTamas Berghammer 2011e209fccSTamas Berghammer error = ReadRegisterRaw(full_reg, reg_value); 2021e209fccSTamas Berghammer 2031e209fccSTamas Berghammer if (error.Success ()) 2041e209fccSTamas Berghammer { 2051e209fccSTamas Berghammer // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 2061e209fccSTamas Berghammer if (is_subreg && (reg_info->byte_offset & 0x1)) 2071e209fccSTamas Berghammer reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 2081e209fccSTamas Berghammer 2091e209fccSTamas Berghammer // If our return byte size was greater than the return value reg size, then 2101e209fccSTamas Berghammer // use the type specified by reg_info rather than the uint64_t default 2111e209fccSTamas Berghammer if (reg_value.GetByteSize() > reg_info->byte_size) 2121e209fccSTamas Berghammer reg_value.SetType(reg_info); 2131e209fccSTamas Berghammer } 2141e209fccSTamas Berghammer return error; 2151e209fccSTamas Berghammer } 2161e209fccSTamas Berghammer 2171e209fccSTamas Berghammer // Get pointer to m_fpr variable and set the data from it. 2181e209fccSTamas Berghammer assert (reg_info->byte_offset < sizeof m_fpr); 2191e209fccSTamas Berghammer uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; 2201e209fccSTamas Berghammer switch (reg_info->byte_size) 2211e209fccSTamas Berghammer { 2221e209fccSTamas Berghammer case 2: 2231e209fccSTamas Berghammer reg_value.SetUInt16(*(uint16_t *)src); 2241e209fccSTamas Berghammer break; 2251e209fccSTamas Berghammer case 4: 2261e209fccSTamas Berghammer reg_value.SetUInt32(*(uint32_t *)src); 2271e209fccSTamas Berghammer break; 2281e209fccSTamas Berghammer case 8: 2291e209fccSTamas Berghammer reg_value.SetUInt64(*(uint64_t *)src); 2301e209fccSTamas Berghammer break; 2311e209fccSTamas Berghammer default: 2321e209fccSTamas Berghammer assert(false && "Unhandled data size."); 2331e209fccSTamas Berghammer error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); 2341e209fccSTamas Berghammer break; 2351e209fccSTamas Berghammer } 2361e209fccSTamas Berghammer 2371e209fccSTamas Berghammer return error; 2381e209fccSTamas Berghammer } 2391e209fccSTamas Berghammer 240*db264a6dSTamas Berghammer Error 2411e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 2421e209fccSTamas Berghammer { 2431e209fccSTamas Berghammer if (!reg_info) 2441e209fccSTamas Berghammer return Error ("reg_info NULL"); 2451e209fccSTamas Berghammer 2461e209fccSTamas Berghammer const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 2471e209fccSTamas Berghammer if (reg_index == LLDB_INVALID_REGNUM) 2481e209fccSTamas Berghammer return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 2491e209fccSTamas Berghammer 2501e209fccSTamas Berghammer if (IsGPR(reg_index)) 2511e209fccSTamas Berghammer return WriteRegisterRaw(reg_index, reg_value); 2521e209fccSTamas Berghammer 2531e209fccSTamas Berghammer if (IsFPR(reg_index)) 2541e209fccSTamas Berghammer { 2551e209fccSTamas Berghammer // Get pointer to m_fpr variable and set the data to it. 2561e209fccSTamas Berghammer assert (reg_info->byte_offset < sizeof(m_fpr)); 2571e209fccSTamas Berghammer uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset; 2581e209fccSTamas Berghammer switch (reg_info->byte_size) 2591e209fccSTamas Berghammer { 2601e209fccSTamas Berghammer case 2: 2611e209fccSTamas Berghammer *(uint16_t *)dst = reg_value.GetAsUInt16(); 2621e209fccSTamas Berghammer break; 2631e209fccSTamas Berghammer case 4: 2641e209fccSTamas Berghammer *(uint32_t *)dst = reg_value.GetAsUInt32(); 2651e209fccSTamas Berghammer break; 2661e209fccSTamas Berghammer case 8: 2671e209fccSTamas Berghammer *(uint64_t *)dst = reg_value.GetAsUInt64(); 2681e209fccSTamas Berghammer break; 2691e209fccSTamas Berghammer default: 2701e209fccSTamas Berghammer assert(false && "Unhandled data size."); 2711e209fccSTamas Berghammer return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 2721e209fccSTamas Berghammer } 2731e209fccSTamas Berghammer 2741e209fccSTamas Berghammer if (!WriteFPR()) 2751e209fccSTamas Berghammer { 2761e209fccSTamas Berghammer return Error ("NativeRegisterContextLinux_arm64::WriteRegister: WriteFPR failed"); 2771e209fccSTamas Berghammer } 2781e209fccSTamas Berghammer 2791e209fccSTamas Berghammer return Error (); 2801e209fccSTamas Berghammer } 2811e209fccSTamas Berghammer 2821e209fccSTamas Berghammer return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 2831e209fccSTamas Berghammer } 2841e209fccSTamas Berghammer 285*db264a6dSTamas Berghammer Error 2861e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 2871e209fccSTamas Berghammer { 2881e209fccSTamas Berghammer Error error; 2891e209fccSTamas Berghammer 290*db264a6dSTamas Berghammer data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 2911e209fccSTamas Berghammer if (!data_sp) 2921e209fccSTamas Berghammer return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); 2931e209fccSTamas Berghammer 2941e209fccSTamas Berghammer if (!ReadGPR ()) 2951e209fccSTamas Berghammer { 2961e209fccSTamas Berghammer error.SetErrorString ("ReadGPR() failed"); 2971e209fccSTamas Berghammer return error; 2981e209fccSTamas Berghammer } 2991e209fccSTamas Berghammer 3001e209fccSTamas Berghammer if (!ReadFPR ()) 3011e209fccSTamas Berghammer { 3021e209fccSTamas Berghammer error.SetErrorString ("ReadFPR() failed"); 3031e209fccSTamas Berghammer return error; 3041e209fccSTamas Berghammer } 3051e209fccSTamas Berghammer 3061e209fccSTamas Berghammer uint8_t *dst = data_sp->GetBytes (); 3071e209fccSTamas Berghammer if (dst == nullptr) 3081e209fccSTamas Berghammer { 3091e209fccSTamas Berghammer error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); 3101e209fccSTamas Berghammer return error; 3111e209fccSTamas Berghammer } 3121e209fccSTamas Berghammer 3131e209fccSTamas Berghammer ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); 3141e209fccSTamas Berghammer dst += GetGPRSize(); 3151e209fccSTamas Berghammer ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 3161e209fccSTamas Berghammer 3171e209fccSTamas Berghammer return error; 3181e209fccSTamas Berghammer } 3191e209fccSTamas Berghammer 320*db264a6dSTamas Berghammer Error 3211e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 3221e209fccSTamas Berghammer { 3231e209fccSTamas Berghammer Error error; 3241e209fccSTamas Berghammer 3251e209fccSTamas Berghammer if (!data_sp) 3261e209fccSTamas Berghammer { 3271e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 3281e209fccSTamas Berghammer return error; 3291e209fccSTamas Berghammer } 3301e209fccSTamas Berghammer 3311e209fccSTamas Berghammer if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 3321e209fccSTamas Berghammer { 3331e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); 3341e209fccSTamas Berghammer return error; 3351e209fccSTamas Berghammer } 3361e209fccSTamas Berghammer 3371e209fccSTamas Berghammer 3381e209fccSTamas Berghammer uint8_t *src = data_sp->GetBytes (); 3391e209fccSTamas Berghammer if (src == nullptr) 3401e209fccSTamas Berghammer { 3411e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 3421e209fccSTamas Berghammer return error; 3431e209fccSTamas Berghammer } 3441e209fccSTamas Berghammer ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); 3451e209fccSTamas Berghammer 3461e209fccSTamas Berghammer if (!WriteGPR ()) 3471e209fccSTamas Berghammer { 3481e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); 3491e209fccSTamas Berghammer return error; 3501e209fccSTamas Berghammer } 3511e209fccSTamas Berghammer 3521e209fccSTamas Berghammer src += GetRegisterInfoInterface ().GetGPRSize (); 3531e209fccSTamas Berghammer ::memcpy (&m_fpr, src, sizeof(m_fpr)); 3541e209fccSTamas Berghammer 3551e209fccSTamas Berghammer if (!WriteFPR ()) 3561e209fccSTamas Berghammer { 3571e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); 3581e209fccSTamas Berghammer return error; 3591e209fccSTamas Berghammer } 3601e209fccSTamas Berghammer 3611e209fccSTamas Berghammer return error; 3621e209fccSTamas Berghammer } 3631e209fccSTamas Berghammer 364*db264a6dSTamas Berghammer Error 3651e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value) 3661e209fccSTamas Berghammer { 3671e209fccSTamas Berghammer Error error; 3681e209fccSTamas Berghammer 3691e209fccSTamas Berghammer uint32_t reg_to_write = reg_index; 3701e209fccSTamas Berghammer RegisterValue value_to_write = reg_value; 3711e209fccSTamas Berghammer 3721e209fccSTamas Berghammer // Check if this is a subregister of a full register. 3731e209fccSTamas Berghammer const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); 3741e209fccSTamas Berghammer if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) 3751e209fccSTamas Berghammer { 3761e209fccSTamas Berghammer RegisterValue full_value; 3771e209fccSTamas Berghammer uint32_t full_reg = reg_info->invalidate_regs[0]; 3781e209fccSTamas Berghammer const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); 3791e209fccSTamas Berghammer 3801e209fccSTamas Berghammer // Read the full register. 3811e209fccSTamas Berghammer error = ReadRegister(full_reg_info, full_value); 3821e209fccSTamas Berghammer if (error.Fail ()) 3831e209fccSTamas Berghammer return error; 3841e209fccSTamas Berghammer 3851e209fccSTamas Berghammer lldb::ByteOrder byte_order = GetByteOrder(); 3861e209fccSTamas Berghammer uint8_t dst[RegisterValue::kMaxRegisterByteSize]; 3871e209fccSTamas Berghammer 3881e209fccSTamas Berghammer // Get the bytes for the full register. 3891e209fccSTamas Berghammer const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, 3901e209fccSTamas Berghammer dst, 3911e209fccSTamas Berghammer sizeof(dst), 3921e209fccSTamas Berghammer byte_order, 3931e209fccSTamas Berghammer error); 3941e209fccSTamas Berghammer if (error.Success() && dest_size) 3951e209fccSTamas Berghammer { 3961e209fccSTamas Berghammer uint8_t src[RegisterValue::kMaxRegisterByteSize]; 3971e209fccSTamas Berghammer 3981e209fccSTamas Berghammer // Get the bytes for the source data. 3991e209fccSTamas Berghammer const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); 4001e209fccSTamas Berghammer if (error.Success() && src_size && (src_size < dest_size)) 4011e209fccSTamas Berghammer { 4021e209fccSTamas Berghammer // Copy the src bytes to the destination. 4031e209fccSTamas Berghammer memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); 4041e209fccSTamas Berghammer // Set this full register as the value to write. 4051e209fccSTamas Berghammer value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); 4061e209fccSTamas Berghammer value_to_write.SetType(full_reg_info); 4071e209fccSTamas Berghammer reg_to_write = full_reg; 4081e209fccSTamas Berghammer } 4091e209fccSTamas Berghammer } 4101e209fccSTamas Berghammer } 4111e209fccSTamas Berghammer 4121e209fccSTamas Berghammer NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 4131e209fccSTamas Berghammer if (!process_sp) 4141e209fccSTamas Berghammer { 4151e209fccSTamas Berghammer error.SetErrorString ("NativeProcessProtocol is NULL"); 4161e209fccSTamas Berghammer return error; 4171e209fccSTamas Berghammer } 4181e209fccSTamas Berghammer 4191e209fccSTamas Berghammer const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write); 4201e209fccSTamas Berghammer assert (register_to_write_info_p && "register to write does not have valid RegisterInfo"); 4211e209fccSTamas Berghammer if (!register_to_write_info_p) 4221e209fccSTamas Berghammer { 4231e209fccSTamas Berghammer error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); 4241e209fccSTamas Berghammer return error; 4251e209fccSTamas Berghammer } 4261e209fccSTamas Berghammer 4271e209fccSTamas Berghammer NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 4281e209fccSTamas Berghammer return process_p->WriteRegisterValue(m_thread.GetID(), 4291e209fccSTamas Berghammer register_to_write_info_p->byte_offset, 4301e209fccSTamas Berghammer register_to_write_info_p->name, 4311e209fccSTamas Berghammer value_to_write); 4321e209fccSTamas Berghammer } 4331e209fccSTamas Berghammer 434*db264a6dSTamas Berghammer Error 4351e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) 4361e209fccSTamas Berghammer { 4371e209fccSTamas Berghammer Error error; 4381e209fccSTamas Berghammer const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); 4391e209fccSTamas Berghammer if (!reg_info) 4401e209fccSTamas Berghammer { 4411e209fccSTamas Berghammer error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); 4421e209fccSTamas Berghammer return error; 4431e209fccSTamas Berghammer } 4441e209fccSTamas Berghammer 4451e209fccSTamas Berghammer NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 4461e209fccSTamas Berghammer if (!process_sp) 4471e209fccSTamas Berghammer { 4481e209fccSTamas Berghammer error.SetErrorString ("NativeProcessProtocol is NULL"); 4491e209fccSTamas Berghammer return error; 4501e209fccSTamas Berghammer } 4511e209fccSTamas Berghammer 4521e209fccSTamas Berghammer NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 4531e209fccSTamas Berghammer return process_p->ReadRegisterValue(m_thread.GetID(), 4541e209fccSTamas Berghammer reg_info->byte_offset, 4551e209fccSTamas Berghammer reg_info->name, 4561e209fccSTamas Berghammer reg_info->byte_size, 4571e209fccSTamas Berghammer reg_value); 4581e209fccSTamas Berghammer } 4591e209fccSTamas Berghammer 4601e209fccSTamas Berghammer bool 4611e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const 4621e209fccSTamas Berghammer { 4631e209fccSTamas Berghammer return reg <= m_reg_info.last_gpr; // GPR's come first. 4641e209fccSTamas Berghammer } 4651e209fccSTamas Berghammer 4661e209fccSTamas Berghammer bool 4671e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::ReadGPR() 4681e209fccSTamas Berghammer { 4691e209fccSTamas Berghammer NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 4701e209fccSTamas Berghammer if (!process_sp) 4711e209fccSTamas Berghammer return false; 4721e209fccSTamas Berghammer NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 4731e209fccSTamas Berghammer 4741e209fccSTamas Berghammer return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 4751e209fccSTamas Berghammer } 4761e209fccSTamas Berghammer 4771e209fccSTamas Berghammer bool 4781e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::WriteGPR() 4791e209fccSTamas Berghammer { 4801e209fccSTamas Berghammer NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 4811e209fccSTamas Berghammer if (!process_sp) 4821e209fccSTamas Berghammer return false; 4831e209fccSTamas Berghammer NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 4841e209fccSTamas Berghammer 4851e209fccSTamas Berghammer return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 4861e209fccSTamas Berghammer } 4871e209fccSTamas Berghammer 4881e209fccSTamas Berghammer bool 4891e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const 4901e209fccSTamas Berghammer { 4911e209fccSTamas Berghammer return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 4921e209fccSTamas Berghammer } 4931e209fccSTamas Berghammer 4941e209fccSTamas Berghammer bool 4951e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::ReadFPR () 4961e209fccSTamas Berghammer { 4971e209fccSTamas Berghammer NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 4981e209fccSTamas Berghammer if (!process_sp) 4991e209fccSTamas Berghammer return false; 5001e209fccSTamas Berghammer 5011e209fccSTamas Berghammer NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 5021e209fccSTamas Berghammer return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 5031e209fccSTamas Berghammer } 5041e209fccSTamas Berghammer 5051e209fccSTamas Berghammer bool 5061e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::WriteFPR () 5071e209fccSTamas Berghammer { 5081e209fccSTamas Berghammer NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 5091e209fccSTamas Berghammer if (!process_sp) 5101e209fccSTamas Berghammer return false; 5111e209fccSTamas Berghammer 5121e209fccSTamas Berghammer NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 5131e209fccSTamas Berghammer return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 5141e209fccSTamas Berghammer } 5151e209fccSTamas Berghammer 5161e209fccSTamas Berghammer lldb::ByteOrder 5171e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::GetByteOrder() const 5181e209fccSTamas Berghammer { 5191e209fccSTamas Berghammer // Get the target process whose privileged thread was used for the register read. 5201e209fccSTamas Berghammer lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; 5211e209fccSTamas Berghammer 5221e209fccSTamas Berghammer NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 5231e209fccSTamas Berghammer if (!process_sp) 5241e209fccSTamas Berghammer return byte_order; 5251e209fccSTamas Berghammer 5261e209fccSTamas Berghammer if (!process_sp->GetByteOrder (byte_order)) 5271e209fccSTamas Berghammer { 5281e209fccSTamas Berghammer // FIXME log here 5291e209fccSTamas Berghammer } 5301e209fccSTamas Berghammer 5311e209fccSTamas Berghammer return byte_order; 5321e209fccSTamas Berghammer } 5331e209fccSTamas Berghammer 5341e209fccSTamas Berghammer size_t 5351e209fccSTamas Berghammer NativeRegisterContextLinux_arm64::GetGPRSize() const 5361e209fccSTamas Berghammer { 5371e209fccSTamas Berghammer return GetRegisterInfoInterface().GetGPRSize(); 5381e209fccSTamas Berghammer } 539