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 
103f57216cSOmair Javaid #include "NativeRegisterContextLinux_arm.h"
113f57216cSOmair Javaid 
123f57216cSOmair Javaid #include "lldb/lldb-private-forward.h"
133f57216cSOmair Javaid #include "lldb/Core/DataBufferHeap.h"
143f57216cSOmair Javaid #include "lldb/Core/Error.h"
153f57216cSOmair Javaid #include "lldb/Core/RegisterValue.h"
163f57216cSOmair Javaid #include "lldb/Host/common/NativeProcessProtocol.h"
173f57216cSOmair Javaid #include "lldb/Host/common/NativeThreadProtocol.h"
183f57216cSOmair Javaid #include "Plugins/Process/Linux/NativeProcessLinux.h"
193f57216cSOmair Javaid 
203f57216cSOmair Javaid #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
213f57216cSOmair Javaid 
223f57216cSOmair Javaid using namespace lldb;
233f57216cSOmair Javaid using namespace lldb_private;
243f57216cSOmair Javaid using namespace lldb_private::process_linux;
253f57216cSOmair Javaid 
263f57216cSOmair Javaid // arm general purpose registers.
273f57216cSOmair Javaid static const uint32_t g_gpr_regnums_arm[] =
283f57216cSOmair Javaid {
293f57216cSOmair Javaid     gpr_r0_arm,
303f57216cSOmair Javaid     gpr_r1_arm,
313f57216cSOmair Javaid     gpr_r2_arm,
323f57216cSOmair Javaid     gpr_r3_arm,
333f57216cSOmair Javaid     gpr_r4_arm,
343f57216cSOmair Javaid     gpr_r5_arm,
353f57216cSOmair Javaid     gpr_r6_arm,
363f57216cSOmair Javaid     gpr_r7_arm,
373f57216cSOmair Javaid     gpr_r8_arm,
383f57216cSOmair Javaid     gpr_r9_arm,
393f57216cSOmair Javaid     gpr_r10_arm,
403f57216cSOmair Javaid     gpr_r11_arm,
413f57216cSOmair Javaid     gpr_r12_arm,
423f57216cSOmair Javaid     gpr_sp_arm,
433f57216cSOmair Javaid     gpr_lr_arm,
443f57216cSOmair Javaid     gpr_pc_arm,
453f57216cSOmair Javaid     gpr_cpsr_arm,
463f57216cSOmair Javaid     LLDB_INVALID_REGNUM // register sets need to end with this flag
473f57216cSOmair Javaid };
483f57216cSOmair Javaid static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \
493f57216cSOmair Javaid               "g_gpr_regnums_arm has wrong number of register infos");
503f57216cSOmair Javaid 
513f57216cSOmair Javaid // arm floating point registers.
523f57216cSOmair Javaid static const uint32_t g_fpu_regnums_arm[] =
533f57216cSOmair Javaid {
543f57216cSOmair Javaid     fpu_s0_arm,
553f57216cSOmair Javaid     fpu_s1_arm,
563f57216cSOmair Javaid     fpu_s2_arm,
573f57216cSOmair Javaid     fpu_s3_arm,
583f57216cSOmair Javaid     fpu_s4_arm,
593f57216cSOmair Javaid     fpu_s5_arm,
603f57216cSOmair Javaid     fpu_s6_arm,
613f57216cSOmair Javaid     fpu_s7_arm,
623f57216cSOmair Javaid     fpu_s8_arm,
633f57216cSOmair Javaid     fpu_s9_arm,
643f57216cSOmair Javaid     fpu_s10_arm,
653f57216cSOmair Javaid     fpu_s11_arm,
663f57216cSOmair Javaid     fpu_s12_arm,
673f57216cSOmair Javaid     fpu_s13_arm,
683f57216cSOmair Javaid     fpu_s14_arm,
693f57216cSOmair Javaid     fpu_s15_arm,
703f57216cSOmair Javaid     fpu_s16_arm,
713f57216cSOmair Javaid     fpu_s17_arm,
723f57216cSOmair Javaid     fpu_s18_arm,
733f57216cSOmair Javaid     fpu_s19_arm,
743f57216cSOmair Javaid     fpu_s20_arm,
753f57216cSOmair Javaid     fpu_s21_arm,
763f57216cSOmair Javaid     fpu_s22_arm,
773f57216cSOmair Javaid     fpu_s23_arm,
783f57216cSOmair Javaid     fpu_s24_arm,
793f57216cSOmair Javaid     fpu_s25_arm,
803f57216cSOmair Javaid     fpu_s26_arm,
813f57216cSOmair Javaid     fpu_s27_arm,
823f57216cSOmair Javaid     fpu_s28_arm,
833f57216cSOmair Javaid     fpu_s29_arm,
843f57216cSOmair Javaid     fpu_s30_arm,
853f57216cSOmair Javaid     fpu_s31_arm,
863f57216cSOmair Javaid     fpu_fpscr_arm,
873f57216cSOmair Javaid     LLDB_INVALID_REGNUM // register sets need to end with this flag
883f57216cSOmair Javaid };
893f57216cSOmair Javaid static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \
903f57216cSOmair Javaid               "g_fpu_regnums_arm has wrong number of register infos");
913f57216cSOmair Javaid 
923f57216cSOmair Javaid namespace {
933f57216cSOmair Javaid     // Number of register sets provided by this context.
943f57216cSOmair Javaid     enum
953f57216cSOmair Javaid     {
963f57216cSOmair Javaid         k_num_register_sets = 2
973f57216cSOmair Javaid     };
983f57216cSOmair Javaid }
993f57216cSOmair Javaid 
1003f57216cSOmair Javaid // Register sets for arm.
1013f57216cSOmair Javaid static const RegisterSet
1023f57216cSOmair Javaid g_reg_sets_arm[k_num_register_sets] =
1033f57216cSOmair Javaid {
1043f57216cSOmair Javaid     { "General Purpose Registers",  "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm },
1053f57216cSOmair Javaid     { "Floating Point Registers",   "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
1063f57216cSOmair Javaid };
1073f57216cSOmair Javaid 
1083f57216cSOmair Javaid NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (
1093f57216cSOmair Javaid         NativeThreadProtocol &native_thread,
1103f57216cSOmair Javaid         uint32_t concrete_frame_idx,
1113f57216cSOmair Javaid         RegisterInfoInterface *reg_info_interface_p) :
1123f57216cSOmair Javaid     NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p)
1133f57216cSOmair Javaid {
1143f57216cSOmair Javaid     switch (reg_info_interface_p->m_target_arch.GetMachine())
1153f57216cSOmair Javaid     {
1163f57216cSOmair Javaid         case llvm::Triple::arm:
1173f57216cSOmair Javaid             m_reg_info.num_registers     = k_num_registers_arm;
1183f57216cSOmair Javaid             m_reg_info.num_gpr_registers = k_num_gpr_registers_arm;
1193f57216cSOmair Javaid             m_reg_info.num_fpr_registers = k_num_fpr_registers_arm;
1203f57216cSOmair Javaid             m_reg_info.last_gpr          = k_last_gpr_arm;
1213f57216cSOmair Javaid             m_reg_info.first_fpr         = k_first_fpr_arm;
1223f57216cSOmair Javaid             m_reg_info.last_fpr          = k_last_fpr_arm;
1233f57216cSOmair Javaid             m_reg_info.first_fpr_v       = fpu_s0_arm;
1243f57216cSOmair Javaid             m_reg_info.last_fpr_v        = fpu_s31_arm;
1253f57216cSOmair Javaid             m_reg_info.gpr_flags         = gpr_cpsr_arm;
1263f57216cSOmair Javaid             break;
1273f57216cSOmair Javaid         default:
1283f57216cSOmair Javaid             assert(false && "Unhandled target architecture.");
1293f57216cSOmair Javaid             break;
1303f57216cSOmair Javaid     }
1313f57216cSOmair Javaid 
1323f57216cSOmair Javaid     ::memset(&m_fpr, 0, sizeof (m_fpr));
1333f57216cSOmair Javaid     ::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm));
1343f57216cSOmair Javaid }
1353f57216cSOmair Javaid 
1363f57216cSOmair Javaid uint32_t
1373f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetRegisterSetCount () const
1383f57216cSOmair Javaid {
1393f57216cSOmair Javaid     return k_num_register_sets;
1403f57216cSOmair Javaid }
1413f57216cSOmair Javaid 
1423f57216cSOmair Javaid const RegisterSet *
1433f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const
1443f57216cSOmair Javaid {
1453f57216cSOmair Javaid     if (set_index < k_num_register_sets)
1463f57216cSOmair Javaid         return &g_reg_sets_arm[set_index];
1473f57216cSOmair Javaid 
1483f57216cSOmair Javaid     return nullptr;
1493f57216cSOmair Javaid }
1503f57216cSOmair Javaid 
1513f57216cSOmair Javaid Error
1523f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
1533f57216cSOmair Javaid {
1543f57216cSOmair Javaid     Error error;
1553f57216cSOmair Javaid 
1563f57216cSOmair Javaid     if (!reg_info)
1573f57216cSOmair Javaid     {
1583f57216cSOmair Javaid         error.SetErrorString ("reg_info NULL");
1593f57216cSOmair Javaid         return error;
1603f57216cSOmair Javaid     }
1613f57216cSOmair Javaid 
1623f57216cSOmair Javaid     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
1633f57216cSOmair Javaid 
1643f57216cSOmair Javaid     if (IsFPR(reg))
1653f57216cSOmair Javaid     {
1663f57216cSOmair Javaid         if (!ReadFPR())
1673f57216cSOmair Javaid         {
1683f57216cSOmair Javaid             error.SetErrorString ("failed to read floating point register");
1693f57216cSOmair Javaid             return error;
1703f57216cSOmair Javaid         }
1713f57216cSOmair Javaid     }
1723f57216cSOmair Javaid     else
1733f57216cSOmair Javaid     {
1743f57216cSOmair Javaid         uint32_t full_reg = reg;
1753f57216cSOmair Javaid         bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
1763f57216cSOmair Javaid 
1773f57216cSOmair Javaid         if (is_subreg)
1783f57216cSOmair Javaid         {
1793f57216cSOmair Javaid             // Read the full aligned 64-bit register.
1803f57216cSOmair Javaid             full_reg = reg_info->invalidate_regs[0];
1813f57216cSOmair Javaid         }
1823f57216cSOmair Javaid 
1833f57216cSOmair Javaid         error = ReadRegisterRaw(full_reg, reg_value);
1843f57216cSOmair Javaid 
1853f57216cSOmair Javaid         if (error.Success ())
1863f57216cSOmair Javaid         {
1873f57216cSOmair Javaid             // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
1883f57216cSOmair Javaid             if (is_subreg && (reg_info->byte_offset & 0x1))
1893f57216cSOmair Javaid                 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
1903f57216cSOmair Javaid 
1913f57216cSOmair Javaid             // If our return byte size was greater than the return value reg size, then
1923f57216cSOmair Javaid             // use the type specified by reg_info rather than the uint64_t default
1933f57216cSOmair Javaid             if (reg_value.GetByteSize() > reg_info->byte_size)
1943f57216cSOmair Javaid                 reg_value.SetType(reg_info);
1953f57216cSOmair Javaid         }
1963f57216cSOmair Javaid         return error;
1973f57216cSOmair Javaid     }
1983f57216cSOmair Javaid 
1993f57216cSOmair Javaid     // Get pointer to m_fpr variable and set the data from it.
2003f57216cSOmair Javaid     assert (reg_info->byte_offset < sizeof m_fpr);
2013f57216cSOmair Javaid     uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
2023f57216cSOmair Javaid     switch (reg_info->byte_size)
2033f57216cSOmair Javaid     {
2043f57216cSOmair Javaid         case 2:
2053f57216cSOmair Javaid             reg_value.SetUInt16(*(uint16_t *)src);
2063f57216cSOmair Javaid             break;
2073f57216cSOmair Javaid         case 4:
2083f57216cSOmair Javaid             reg_value.SetUInt32(*(uint32_t *)src);
2093f57216cSOmair Javaid             break;
2103f57216cSOmair Javaid         case 8:
2113f57216cSOmair Javaid             reg_value.SetUInt64(*(uint64_t *)src);
2123f57216cSOmair Javaid             break;
2133f57216cSOmair Javaid         default:
2143f57216cSOmair Javaid             assert(false && "Unhandled data size.");
2153f57216cSOmair Javaid             error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
2163f57216cSOmair Javaid             break;
2173f57216cSOmair Javaid     }
2183f57216cSOmair Javaid 
2193f57216cSOmair Javaid     return error;
2203f57216cSOmair Javaid }
2213f57216cSOmair Javaid 
2223f57216cSOmair Javaid Error
2233f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
2243f57216cSOmair Javaid {
2253f57216cSOmair Javaid     if (!reg_info)
2263f57216cSOmair Javaid         return Error ("reg_info NULL");
2273f57216cSOmair Javaid 
2283f57216cSOmair Javaid     const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
2293f57216cSOmair Javaid     if (reg_index == LLDB_INVALID_REGNUM)
2303f57216cSOmair Javaid         return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
2313f57216cSOmair Javaid 
2323f57216cSOmair Javaid     if (IsGPR(reg_index))
2333f57216cSOmair Javaid         return WriteRegisterRaw(reg_index, reg_value);
2343f57216cSOmair Javaid 
2353f57216cSOmair Javaid     if (IsFPR(reg_index))
2363f57216cSOmair Javaid     {
2373f57216cSOmair Javaid         // Get pointer to m_fpr variable and set the data to it.
2383f57216cSOmair Javaid         assert (reg_info->byte_offset < sizeof(m_fpr));
2393f57216cSOmair Javaid         uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
2403f57216cSOmair Javaid         switch (reg_info->byte_size)
2413f57216cSOmair Javaid         {
2423f57216cSOmair Javaid             case 2:
2433f57216cSOmair Javaid                 *(uint16_t *)dst = reg_value.GetAsUInt16();
2443f57216cSOmair Javaid                 break;
2453f57216cSOmair Javaid             case 4:
2463f57216cSOmair Javaid                 *(uint32_t *)dst = reg_value.GetAsUInt32();
2473f57216cSOmair Javaid                 break;
2483f57216cSOmair Javaid             case 8:
2493f57216cSOmair Javaid                 *(uint64_t *)dst = reg_value.GetAsUInt64();
2503f57216cSOmair Javaid                 break;
2513f57216cSOmair Javaid             default:
2523f57216cSOmair Javaid                 assert(false && "Unhandled data size.");
2533f57216cSOmair Javaid                 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
2543f57216cSOmair Javaid         }
2553f57216cSOmair Javaid 
2563f57216cSOmair Javaid         if (!WriteFPR())
2573f57216cSOmair Javaid         {
2583f57216cSOmair Javaid             return Error ("NativeRegisterContextLinux_arm::WriteRegister: WriteFPR failed");
2593f57216cSOmair Javaid         }
2603f57216cSOmair Javaid 
2613f57216cSOmair Javaid         return Error ();
2623f57216cSOmair Javaid     }
2633f57216cSOmair Javaid 
2643f57216cSOmair Javaid     return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
2653f57216cSOmair Javaid }
2663f57216cSOmair Javaid 
2673f57216cSOmair Javaid Error
2683f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
2693f57216cSOmair Javaid {
2703f57216cSOmair Javaid     Error error;
2713f57216cSOmair Javaid 
2723f57216cSOmair Javaid     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
2733f57216cSOmair Javaid     if (!data_sp)
274*bef47e49SGreg Clayton         return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE);
2753f57216cSOmair Javaid 
2763f57216cSOmair Javaid     if (!ReadGPR ())
2773f57216cSOmair Javaid     {
2783f57216cSOmair Javaid         error.SetErrorString ("ReadGPR() failed");
2793f57216cSOmair Javaid         return error;
2803f57216cSOmair Javaid     }
2813f57216cSOmair Javaid 
2823f57216cSOmair Javaid     if (!ReadFPR ())
2833f57216cSOmair Javaid     {
2843f57216cSOmair Javaid         error.SetErrorString ("ReadFPR() failed");
2853f57216cSOmair Javaid         return error;
2863f57216cSOmair Javaid     }
2873f57216cSOmair Javaid 
2883f57216cSOmair Javaid     uint8_t *dst = data_sp->GetBytes ();
2893f57216cSOmair Javaid     if (dst == nullptr)
2903f57216cSOmair Javaid     {
291*bef47e49SGreg Clayton         error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE);
2923f57216cSOmair Javaid         return error;
2933f57216cSOmair Javaid     }
2943f57216cSOmair Javaid 
2953f57216cSOmair Javaid     ::memcpy (dst, &m_gpr_arm, GetGPRSize());
2963f57216cSOmair Javaid     dst += GetGPRSize();
2973f57216cSOmair Javaid     ::memcpy (dst, &m_fpr, sizeof(m_fpr));
2983f57216cSOmair Javaid 
2993f57216cSOmair Javaid     return error;
3003f57216cSOmair Javaid }
3013f57216cSOmair Javaid 
3023f57216cSOmair Javaid Error
3033f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
3043f57216cSOmair Javaid {
3053f57216cSOmair Javaid     Error error;
3063f57216cSOmair Javaid 
3073f57216cSOmair Javaid     if (!data_sp)
3083f57216cSOmair Javaid     {
3093f57216cSOmair Javaid         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
3103f57216cSOmair Javaid         return error;
3113f57216cSOmair Javaid     }
3123f57216cSOmair Javaid 
3133f57216cSOmair Javaid     if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
3143f57216cSOmair Javaid     {
315*bef47e49SGreg 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 ());
3163f57216cSOmair Javaid         return error;
3173f57216cSOmair Javaid     }
3183f57216cSOmair Javaid 
3193f57216cSOmair Javaid 
3203f57216cSOmair Javaid     uint8_t *src = data_sp->GetBytes ();
3213f57216cSOmair Javaid     if (src == nullptr)
3223f57216cSOmair Javaid     {
3233f57216cSOmair Javaid         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
3243f57216cSOmair Javaid         return error;
3253f57216cSOmair Javaid     }
3263f57216cSOmair Javaid     ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ());
3273f57216cSOmair Javaid 
3283f57216cSOmair Javaid     if (!WriteGPR ())
3293f57216cSOmair Javaid     {
3303f57216cSOmair Javaid         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__);
3313f57216cSOmair Javaid         return error;
3323f57216cSOmair Javaid     }
3333f57216cSOmair Javaid 
3343f57216cSOmair Javaid     src += GetRegisterInfoInterface ().GetGPRSize ();
3353f57216cSOmair Javaid     ::memcpy (&m_fpr, src, sizeof(m_fpr));
3363f57216cSOmair Javaid 
3373f57216cSOmair Javaid     if (!WriteFPR ())
3383f57216cSOmair Javaid     {
3393f57216cSOmair Javaid         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__);
3403f57216cSOmair Javaid         return error;
3413f57216cSOmair Javaid     }
3423f57216cSOmair Javaid 
3433f57216cSOmair Javaid     return error;
3443f57216cSOmair Javaid }
3453f57216cSOmair Javaid 
3463f57216cSOmair Javaid Error
3473f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteRegisterRaw (uint32_t reg_index, const RegisterValue &reg_value)
3483f57216cSOmair Javaid {
3493f57216cSOmair Javaid     Error error;
3503f57216cSOmair Javaid 
3513f57216cSOmair Javaid     uint32_t reg_to_write = reg_index;
3523f57216cSOmair Javaid     RegisterValue value_to_write = reg_value;
3533f57216cSOmair Javaid 
3543f57216cSOmair Javaid     // Check if this is a subregister of a full register.
3553f57216cSOmair Javaid     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
3563f57216cSOmair Javaid     if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
3573f57216cSOmair Javaid     {
3583f57216cSOmair Javaid         RegisterValue full_value;
3593f57216cSOmair Javaid         uint32_t full_reg = reg_info->invalidate_regs[0];
3603f57216cSOmair Javaid         const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
3613f57216cSOmair Javaid 
3623f57216cSOmair Javaid         // Read the full register.
3633f57216cSOmair Javaid         error = ReadRegister(full_reg_info, full_value);
3643f57216cSOmair Javaid         if (error.Fail ())
3653f57216cSOmair Javaid             return error;
3663f57216cSOmair Javaid 
3673f57216cSOmair Javaid         lldb::ByteOrder byte_order = GetByteOrder();
3683f57216cSOmair Javaid         uint8_t dst[RegisterValue::kMaxRegisterByteSize];
3693f57216cSOmair Javaid 
3703f57216cSOmair Javaid         // Get the bytes for the full register.
3713f57216cSOmair Javaid         const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
3723f57216cSOmair Javaid                                                                dst,
3733f57216cSOmair Javaid                                                                sizeof(dst),
3743f57216cSOmair Javaid                                                                byte_order,
3753f57216cSOmair Javaid                                                                error);
3763f57216cSOmair Javaid         if (error.Success() && dest_size)
3773f57216cSOmair Javaid         {
3783f57216cSOmair Javaid             uint8_t src[RegisterValue::kMaxRegisterByteSize];
3793f57216cSOmair Javaid 
3803f57216cSOmair Javaid             // Get the bytes for the source data.
3813f57216cSOmair Javaid             const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
3823f57216cSOmair Javaid             if (error.Success() && src_size && (src_size < dest_size))
3833f57216cSOmair Javaid             {
3843f57216cSOmair Javaid                 // Copy the src bytes to the destination.
3853f57216cSOmair Javaid                 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
3863f57216cSOmair Javaid                 // Set this full register as the value to write.
3873f57216cSOmair Javaid                 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
3883f57216cSOmair Javaid                 value_to_write.SetType(full_reg_info);
3893f57216cSOmair Javaid                 reg_to_write = full_reg;
3903f57216cSOmair Javaid             }
3913f57216cSOmair Javaid         }
3923f57216cSOmair Javaid     }
3933f57216cSOmair Javaid 
3943f57216cSOmair Javaid     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
3953f57216cSOmair Javaid     if (!process_sp)
3963f57216cSOmair Javaid     {
3973f57216cSOmair Javaid         error.SetErrorString ("NativeProcessProtocol is NULL");
3983f57216cSOmair Javaid         return error;
3993f57216cSOmair Javaid     }
4003f57216cSOmair Javaid 
4013f57216cSOmair Javaid     const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
4023f57216cSOmair Javaid     assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
4033f57216cSOmair Javaid     if (!register_to_write_info_p)
4043f57216cSOmair Javaid     {
4053f57216cSOmair Javaid         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
4063f57216cSOmair Javaid         return error;
4073f57216cSOmair Javaid     }
4083f57216cSOmair Javaid 
4093f57216cSOmair Javaid     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
4103f57216cSOmair Javaid     return process_p->WriteRegisterValue(m_thread.GetID(),
4113f57216cSOmair Javaid                                          register_to_write_info_p->byte_offset,
4123f57216cSOmair Javaid                                          register_to_write_info_p->name,
4133f57216cSOmair Javaid                                          value_to_write);
4143f57216cSOmair Javaid }
4153f57216cSOmair Javaid 
4163f57216cSOmair Javaid Error
4173f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadRegisterRaw (uint32_t reg_index, RegisterValue &reg_value)
4183f57216cSOmair Javaid {
4193f57216cSOmair Javaid     Error error;
4203f57216cSOmair Javaid     const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index);
4213f57216cSOmair Javaid     if (!reg_info)
4223f57216cSOmair Javaid     {
4233f57216cSOmair Javaid         error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index);
4243f57216cSOmair Javaid         return error;
4253f57216cSOmair Javaid     }
4263f57216cSOmair Javaid 
4273f57216cSOmair Javaid     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
4283f57216cSOmair Javaid     if (!process_sp)
4293f57216cSOmair Javaid     {
4303f57216cSOmair Javaid         error.SetErrorString ("NativeProcessProtocol is NULL");
4313f57216cSOmair Javaid         return error;
4323f57216cSOmair Javaid     }
4333f57216cSOmair Javaid 
4343f57216cSOmair Javaid     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
4353f57216cSOmair Javaid     return process_p->ReadRegisterValue(m_thread.GetID(),
4363f57216cSOmair Javaid                                         reg_info->byte_offset,
4373f57216cSOmair Javaid                                         reg_info->name,
4383f57216cSOmair Javaid                                         reg_info->byte_size,
4393f57216cSOmair Javaid                                         reg_value);
4403f57216cSOmair Javaid }
4413f57216cSOmair Javaid 
4423f57216cSOmair Javaid bool
4433f57216cSOmair Javaid NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const
4443f57216cSOmair Javaid {
4453f57216cSOmair Javaid     return reg <= m_reg_info.last_gpr;   // GPR's come first.
4463f57216cSOmair Javaid }
4473f57216cSOmair Javaid 
4483f57216cSOmair Javaid bool
4493f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadGPR()
4503f57216cSOmair Javaid {
4513f57216cSOmair Javaid     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
4523f57216cSOmair Javaid     if (!process_sp)
4533f57216cSOmair Javaid         return false;
4543f57216cSOmair Javaid     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
4553f57216cSOmair Javaid 
4563f57216cSOmair Javaid     return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success();
4573f57216cSOmair Javaid }
4583f57216cSOmair Javaid 
4593f57216cSOmair Javaid bool
4603f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteGPR()
4613f57216cSOmair Javaid {
4623f57216cSOmair Javaid     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
4633f57216cSOmair Javaid     if (!process_sp)
4643f57216cSOmair Javaid         return false;
4653f57216cSOmair Javaid     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
4663f57216cSOmair Javaid 
4673f57216cSOmair Javaid     return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success();
4683f57216cSOmair Javaid }
4693f57216cSOmair Javaid 
4703f57216cSOmair Javaid bool
4713f57216cSOmair Javaid NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const
4723f57216cSOmair Javaid {
4733f57216cSOmair Javaid     return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
4743f57216cSOmair Javaid }
4753f57216cSOmair Javaid 
4763f57216cSOmair Javaid bool
4773f57216cSOmair Javaid NativeRegisterContextLinux_arm::ReadFPR ()
4783f57216cSOmair Javaid {
4793f57216cSOmair Javaid     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
4803f57216cSOmair Javaid     if (!process_sp)
4813f57216cSOmair Javaid         return false;
4823f57216cSOmair Javaid 
4833f57216cSOmair Javaid     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
4843f57216cSOmair Javaid     return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success();
4853f57216cSOmair Javaid }
4863f57216cSOmair Javaid 
4873f57216cSOmair Javaid bool
4883f57216cSOmair Javaid NativeRegisterContextLinux_arm::WriteFPR ()
4893f57216cSOmair Javaid {
4903f57216cSOmair Javaid     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
4913f57216cSOmair Javaid     if (!process_sp)
4923f57216cSOmair Javaid         return false;
4933f57216cSOmair Javaid 
4943f57216cSOmair Javaid     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
4953f57216cSOmair Javaid     return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success();
4963f57216cSOmair Javaid }
4973f57216cSOmair Javaid 
4983f57216cSOmair Javaid lldb::ByteOrder
4993f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetByteOrder() const
5003f57216cSOmair Javaid {
5013f57216cSOmair Javaid     // Get the target process whose privileged thread was used for the register read.
5023f57216cSOmair Javaid     lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
5033f57216cSOmair Javaid 
5043f57216cSOmair Javaid     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
5053f57216cSOmair Javaid     if (!process_sp)
5063f57216cSOmair Javaid         return byte_order;
5073f57216cSOmair Javaid 
5083f57216cSOmair Javaid     if (!process_sp->GetByteOrder (byte_order))
5093f57216cSOmair Javaid     {
5103f57216cSOmair Javaid         // FIXME log here
5113f57216cSOmair Javaid     }
5123f57216cSOmair Javaid 
5133f57216cSOmair Javaid     return byte_order;
5143f57216cSOmair Javaid }
5153f57216cSOmair Javaid 
5163f57216cSOmair Javaid size_t
5173f57216cSOmair Javaid NativeRegisterContextLinux_arm::GetGPRSize() const
5183f57216cSOmair Javaid {
5193f57216cSOmair Javaid     return GetRegisterInfoInterface().GetGPRSize();
5203f57216cSOmair Javaid }
521