diff options
author | Jason Molenda <jmolenda@apple.com> | 2015-01-16 02:31:35 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2015-01-16 02:31:35 +0000 |
commit | bcc57859587b4ad278505db352f55e9473180723 (patch) | |
tree | 1b128864e72b0cd3814451fa744db8cc92252eff /lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp | |
parent | e39fb93cf3f62929cfa2b8405dfe4c7b90c0292a (diff) | |
download | bcm5719-llvm-bcc57859587b4ad278505db352f55e9473180723.tar.gz bcm5719-llvm-bcc57859587b4ad278505db352f55e9473180723.zip |
Fixes to DNBArchImpl in debugserver to correctly get/set
the register state when debugging AArch32 programs (armv7
programs running on an armv8 processor). Most notably,
there is no "fpscr" register in the register context -
there is an fpsr and an fpcr.
Also fix a bug where the floating point values could not
be written in armv7 processes.
<rdar://problem/18977767>
llvm-svn: 226244
Diffstat (limited to 'lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp')
-rw-r--r-- | lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp | 181 |
1 files changed, 178 insertions, 3 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp index 999b581d3de..7ffe2c7f010 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp @@ -234,9 +234,62 @@ DNBArchMachARM::GetVFPState(bool force) if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) return KERN_SUCCESS; + kern_return_t kret; + +#if defined (__arm64__) || defined (__aarch64__) + // Read the registers from our thread + mach_msg_type_number_t count = ARM_NEON_STATE_COUNT; + kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE, (thread_state_t)&m_state.context.vfp, &count); + if (DNBLogEnabledForAny (LOG_THREAD)) + { + DNBLogThreaded("thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" + "\n q0 = 0x%16.16llx%16.16llx" + "\n q1 = 0x%16.16llx%16.16llx" + "\n q2 = 0x%16.16llx%16.16llx" + "\n q3 = 0x%16.16llx%16.16llx" + "\n q4 = 0x%16.16llx%16.16llx" + "\n q5 = 0x%16.16llx%16.16llx" + "\n q6 = 0x%16.16llx%16.16llx" + "\n q7 = 0x%16.16llx%16.16llx" + "\n q8 = 0x%16.16llx%16.16llx" + "\n q9 = 0x%16.16llx%16.16llx" + "\n q10 = 0x%16.16llx%16.16llx" + "\n q11 = 0x%16.16llx%16.16llx" + "\n q12 = 0x%16.16llx%16.16llx" + "\n q13 = 0x%16.16llx%16.16llx" + "\n q14 = 0x%16.16llx%16.16llx" + "\n q15 = 0x%16.16llx%16.16llx" + "\n fpsr = 0x%8.8x" + "\n fpcr = 0x%8.8x\n\n", + m_thread->MachPortNumber(), + ARM_NEON_STATE, + ARM_NEON_STATE_COUNT, + kret, + count, + ((uint64_t *)&m_state.context.vfp.__v[0])[0] , ((uint64_t *)&m_state.context.vfp.__v[0])[1], + ((uint64_t *)&m_state.context.vfp.__v[1])[0] , ((uint64_t *)&m_state.context.vfp.__v[1])[1], + ((uint64_t *)&m_state.context.vfp.__v[2])[0] , ((uint64_t *)&m_state.context.vfp.__v[2])[1], + ((uint64_t *)&m_state.context.vfp.__v[3])[0] , ((uint64_t *)&m_state.context.vfp.__v[3])[1], + ((uint64_t *)&m_state.context.vfp.__v[4])[0] , ((uint64_t *)&m_state.context.vfp.__v[4])[1], + ((uint64_t *)&m_state.context.vfp.__v[5])[0] , ((uint64_t *)&m_state.context.vfp.__v[5])[1], + ((uint64_t *)&m_state.context.vfp.__v[6])[0] , ((uint64_t *)&m_state.context.vfp.__v[6])[1], + ((uint64_t *)&m_state.context.vfp.__v[7])[0] , ((uint64_t *)&m_state.context.vfp.__v[7])[1], + ((uint64_t *)&m_state.context.vfp.__v[8])[0] , ((uint64_t *)&m_state.context.vfp.__v[8])[1], + ((uint64_t *)&m_state.context.vfp.__v[9])[0] , ((uint64_t *)&m_state.context.vfp.__v[9])[1], + ((uint64_t *)&m_state.context.vfp.__v[10])[0], ((uint64_t *)&m_state.context.vfp.__v[10])[1], + ((uint64_t *)&m_state.context.vfp.__v[11])[0], ((uint64_t *)&m_state.context.vfp.__v[11])[1], + ((uint64_t *)&m_state.context.vfp.__v[12])[0], ((uint64_t *)&m_state.context.vfp.__v[12])[1], + ((uint64_t *)&m_state.context.vfp.__v[13])[0], ((uint64_t *)&m_state.context.vfp.__v[13])[1], + ((uint64_t *)&m_state.context.vfp.__v[14])[0], ((uint64_t *)&m_state.context.vfp.__v[14])[1], + ((uint64_t *)&m_state.context.vfp.__v[15])[0], ((uint64_t *)&m_state.context.vfp.__v[15])[1], + m_state.context.vfp.__fpsr, + m_state.context.vfp.__fpcr); + + } +#else // Read the registers from our thread mach_msg_type_number_t count = ARM_VFP_STATE_COUNT; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count); + kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count); if (DNBLogEnabledForAny (LOG_THREAD)) { uint32_t *r = &m_state.context.vfp.__r[0]; @@ -255,6 +308,7 @@ DNBArchMachARM::GetVFPState(bool force) DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x s53=%8.8x s54=%8.8x s55=%8.8x",r[48],r[49],r[50],r[51],r[52],r[53],r[54],r[55]); DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x",r[56],r[57],r[58],r[59],r[60],r[61],r[62],r[63],r[64]); } +#endif m_state.SetError(set, Read, kret); return kret; } @@ -322,7 +376,64 @@ kern_return_t DNBArchMachARM::SetVFPState() { int set = e_regSetVFP; - kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, ARM_VFP_STATE_COUNT); + kern_return_t kret; + mach_msg_type_number_t count; + +#if defined (__arm64__) || defined (__aarch64__) + count = ARM_NEON_STATE_COUNT; + kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_NEON_STATE, (thread_state_t)&m_state.context.vfp, count); +#else + count = ARM_VFP_STATE_COUNT; + kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, count); +#endif + +#if defined (__arm64__) || defined (__aarch64__) + if (DNBLogEnabledForAny (LOG_THREAD)) + { + DNBLogThreaded("thread_set_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" + "\n q0 = 0x%16.16llx%16.16llx" + "\n q1 = 0x%16.16llx%16.16llx" + "\n q2 = 0x%16.16llx%16.16llx" + "\n q3 = 0x%16.16llx%16.16llx" + "\n q4 = 0x%16.16llx%16.16llx" + "\n q5 = 0x%16.16llx%16.16llx" + "\n q6 = 0x%16.16llx%16.16llx" + "\n q7 = 0x%16.16llx%16.16llx" + "\n q8 = 0x%16.16llx%16.16llx" + "\n q9 = 0x%16.16llx%16.16llx" + "\n q10 = 0x%16.16llx%16.16llx" + "\n q11 = 0x%16.16llx%16.16llx" + "\n q12 = 0x%16.16llx%16.16llx" + "\n q13 = 0x%16.16llx%16.16llx" + "\n q14 = 0x%16.16llx%16.16llx" + "\n q15 = 0x%16.16llx%16.16llx" + "\n fpsr = 0x%8.8x" + "\n fpcr = 0x%8.8x\n\n", + m_thread->MachPortNumber(), + ARM_NEON_STATE, + ARM_NEON_STATE_COUNT, + kret, + count, + ((uint64_t *)&m_state.context.vfp.__v[0])[0] , ((uint64_t *)&m_state.context.vfp.__v[0])[1], + ((uint64_t *)&m_state.context.vfp.__v[1])[0] , ((uint64_t *)&m_state.context.vfp.__v[1])[1], + ((uint64_t *)&m_state.context.vfp.__v[2])[0] , ((uint64_t *)&m_state.context.vfp.__v[2])[1], + ((uint64_t *)&m_state.context.vfp.__v[3])[0] , ((uint64_t *)&m_state.context.vfp.__v[3])[1], + ((uint64_t *)&m_state.context.vfp.__v[4])[0] , ((uint64_t *)&m_state.context.vfp.__v[4])[1], + ((uint64_t *)&m_state.context.vfp.__v[5])[0] , ((uint64_t *)&m_state.context.vfp.__v[5])[1], + ((uint64_t *)&m_state.context.vfp.__v[6])[0] , ((uint64_t *)&m_state.context.vfp.__v[6])[1], + ((uint64_t *)&m_state.context.vfp.__v[7])[0] , ((uint64_t *)&m_state.context.vfp.__v[7])[1], + ((uint64_t *)&m_state.context.vfp.__v[8])[0] , ((uint64_t *)&m_state.context.vfp.__v[8])[1], + ((uint64_t *)&m_state.context.vfp.__v[9])[0] , ((uint64_t *)&m_state.context.vfp.__v[9])[1], + ((uint64_t *)&m_state.context.vfp.__v[10])[0], ((uint64_t *)&m_state.context.vfp.__v[10])[1], + ((uint64_t *)&m_state.context.vfp.__v[11])[0], ((uint64_t *)&m_state.context.vfp.__v[11])[1], + ((uint64_t *)&m_state.context.vfp.__v[12])[0], ((uint64_t *)&m_state.context.vfp.__v[12])[1], + ((uint64_t *)&m_state.context.vfp.__v[13])[0], ((uint64_t *)&m_state.context.vfp.__v[13])[1], + ((uint64_t *)&m_state.context.vfp.__v[14])[0], ((uint64_t *)&m_state.context.vfp.__v[14])[1], + ((uint64_t *)&m_state.context.vfp.__v[15])[0], ((uint64_t *)&m_state.context.vfp.__v[15])[1], + m_state.context.vfp.__fpsr, + m_state.context.vfp.__fpcr); + } +#endif m_state.SetError(set, Write, kret); // Set the current write error for this register set m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently return kret; // Return the error code @@ -1366,7 +1477,12 @@ enum vfp_q13, vfp_q14, vfp_q15, +#if defined (__arm64__) || defined (__aarch64__) + vfp_fpsr, + vfp_fpcr, +#else vfp_fpscr +#endif }; enum @@ -1551,7 +1667,12 @@ DNBArchMachARM::g_vfp_registers[] = { DEFINE_VFP_Q_IDX (14), NULL, g_invalidate_q14 }, { DEFINE_VFP_Q_IDX (15), NULL, g_invalidate_q15 }, +#if defined (__arm64__) || defined (__aarch64__) + { e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, + { e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpcr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL } +#else { e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL } +#endif }; // Exception registers @@ -1654,28 +1775,55 @@ DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value) // in the enumerated values for case statement below. if (reg >= vfp_s0 && reg <= vfp_s31) { +#if defined (__arm64__) || defined (__aarch64__) + uint32_t *s_reg = ((uint32_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_s0); + memcpy (&value->value.v_uint8, s_reg, 4); +#else value->value.uint32 = m_state.context.vfp.__r[reg]; +#endif return true; } else if (reg >= vfp_d0 && reg <= vfp_d31) { +#if defined (__arm64__) || defined (__aarch64__) + uint64_t *d_reg = ((uint64_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_d0); + memcpy (&value->value.v_uint8, d_reg, 8); +#else uint32_t d_reg_idx = reg - vfp_d0; uint32_t s_reg_idx = d_reg_idx * 2; value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0]; value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1]; +#endif return true; } else if (reg >= vfp_q0 && reg <= vfp_q15) { +#if defined (__arm64__) || defined (__aarch64__) + memcpy (&value->value.v_uint8, (uint8_t *) &m_state.context.vfp.__v[reg - vfp_q0], 16); +#else uint32_t s_reg_idx = (reg - vfp_q0) * 4; memcpy (&value->value.v_uint8, (uint8_t *) &m_state.context.vfp.__r[s_reg_idx], 16); +#endif + return true; + } +#if defined (__arm64__) || defined (__aarch64__) + else if (reg == vfp_fpsr) + { + value->value.uint32 = m_state.context.vfp.__fpsr; + return true; + } + else if (reg == vfp_fpcr) + { + value->value.uint32 = m_state.context.vfp.__fpcr; return true; } +#else else if (reg == vfp_fpscr) { value->value.uint32 = m_state.context.vfp.__fpscr; return true; } +#endif break; case e_regSetEXC: @@ -1750,28 +1898,55 @@ DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value // in the enumerated values for case statement below. if (reg >= vfp_s0 && reg <= vfp_s31) { +#if defined (__arm64__) || defined (__aarch64__) + uint32_t *s_reg = ((uint32_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_s0); + memcpy (s_reg, &value->value.v_uint8, 4); +#else m_state.context.vfp.__r[reg] = value->value.uint32; +#endif success = true; } else if (reg >= vfp_d0 && reg <= vfp_d31) { +#if defined (__arm64__) || defined (__aarch64__) + uint64_t *d_reg = ((uint64_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_d0); + memcpy (d_reg, &value->value.v_uint8, 8); +#else uint32_t d_reg_idx = reg - vfp_d0; uint32_t s_reg_idx = d_reg_idx * 2; m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0]; m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1]; +#endif success = true; } else if (reg >= vfp_q0 && reg <= vfp_q15) { +#if defined (__arm64__) || defined (__aarch64__) + memcpy ((uint8_t *) &m_state.context.vfp.__v[reg - vfp_q0], &value->value.v_uint8, 16); +#else uint32_t s_reg_idx = (reg - vfp_q0) * 4; memcpy ((uint8_t *) &m_state.context.vfp.__r[s_reg_idx], &value->value.v_uint8, 16); - return true; +#endif + success = true; } +#if defined (__arm64__) || defined (__aarch64__) + else if (reg == vfp_fpsr) + { + m_state.context.vfp.__fpsr = value->value.uint32; + success = true; + } + else if (reg == vfp_fpcr) + { + m_state.context.vfp.__fpcr = value->value.uint32; + success = true; + } +#else else if (reg == vfp_fpscr) { m_state.context.vfp.__fpscr = value->value.uint32; success = true; } +#endif break; case e_regSetEXC: |