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
This commit is contained in:
Jason Molenda 2015-01-16 02:31:35 +00:00
parent e39fb93cf3
commit bcc5785958
2 changed files with 187 additions and 11 deletions

View File

@ -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:

View File

@ -109,17 +109,14 @@ protected:
#endif
void EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, uint32_t cpsr, bool currentPCIsThumb, nub_addr_t *nextPC, bool *nextPCIsThumb);
typedef enum RegisterSetTag
{
e_regSetALL = REGISTER_SET_ALL,
e_regSetGPR = ARM_THREAD_STATE,
e_regSetVFP = ARM_VFP_STATE,
e_regSetEXC = ARM_EXCEPTION_STATE,
#if defined (ARM_DEBUG_STATE32) && (defined (__arm64__) || defined (__aarch64__))
e_regSetDBG = ARM_DEBUG_STATE32,
#else
e_regSetDBG = ARM_DEBUG_STATE,
#endif
e_regSetGPR, // ARM_THREAD_STATE
e_regSetVFP, // ARM_VFP_STATE (ARM_NEON_STATE if defined __arm64__)
e_regSetEXC, // ARM_EXCEPTION_STATE
e_regSetDBG, // ARM_DEBUG_STATE (ARM_DEBUG_STATE32 if defined __arm64__)
kNumRegisterSets
} RegisterSet;
@ -131,7 +128,11 @@ protected:
};
typedef arm_thread_state_t GPR;
#if defined (__arm64__) || defined (__aarch64__)
typedef arm_neon_state_t FPU;
#else
typedef arm_vfp_state_t FPU;
#endif
typedef arm_exception_state_t EXC;
static const DNBRegisterInfo g_gpr_registers[];