forked from OSchip/llvm-project
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:
parent
e39fb93cf3
commit
bcc5785958
|
@ -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:
|
||||
|
|
|
@ -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[];
|
||||
|
|
Loading…
Reference in New Issue