const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
native_thread, CreateRegisterInfoInterface(target_arch)),
- m_fpr(), m_dbr() {
+ m_dbr() {
assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize());
}
static constexpr int RegNumX86ToX86_64(int regnum) {
switch (regnum) {
- case lldb_fctrl_i386:
- return lldb_fctrl_x86_64;
- case lldb_fstat_i386:
- return lldb_fstat_x86_64;
- case lldb_ftag_i386:
- return lldb_ftag_x86_64;
- case lldb_fop_i386:
- return lldb_fop_x86_64;
- case lldb_fiseg_i386:
- return lldb_fiseg_x86_64;
- case lldb_fioff_i386:
- return lldb_fioff_x86_64;
- case lldb_foseg_i386:
- return lldb_foseg_x86_64;
- case lldb_fooff_i386:
- return lldb_fooff_x86_64;
- case lldb_mxcsr_i386:
- return lldb_mxcsr_x86_64;
- case lldb_mxcsrmask_i386:
- return lldb_mxcsrmask_x86_64;
- case lldb_st0_i386:
- case lldb_st1_i386:
- case lldb_st2_i386:
- case lldb_st3_i386:
- case lldb_st4_i386:
- case lldb_st5_i386:
- case lldb_st6_i386:
- case lldb_st7_i386:
- return lldb_st0_x86_64 + regnum - lldb_st0_i386;
- case lldb_mm0_i386:
- case lldb_mm1_i386:
- case lldb_mm2_i386:
- case lldb_mm3_i386:
- case lldb_mm4_i386:
- case lldb_mm5_i386:
- case lldb_mm6_i386:
- case lldb_mm7_i386:
- return lldb_mm0_x86_64 + regnum - lldb_mm0_i386;
- case lldb_xmm0_i386:
- case lldb_xmm1_i386:
- case lldb_xmm2_i386:
- case lldb_xmm3_i386:
- case lldb_xmm4_i386:
- case lldb_xmm5_i386:
- case lldb_xmm6_i386:
- case lldb_xmm7_i386:
- return lldb_xmm0_x86_64 + regnum - lldb_xmm0_i386;
case lldb_ymm0_i386:
case lldb_ymm1_i386:
case lldb_ymm2_i386:
case FPRegSet:
#if defined(__x86_64__)
return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, m_thread.GetID(),
- &m_fpr);
+ m_fpr.data());
#else
return NativeProcessFreeBSD::PtraceWrapper(PT_GETXMMREGS, m_thread.GetID(),
- &m_fpr);
+ m_fpr.data());
#endif
case DBRegSet:
return NativeProcessFreeBSD::PtraceWrapper(PT_GETDBREGS, m_thread.GetID(),
case FPRegSet:
#if defined(__x86_64__)
return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, m_thread.GetID(),
- &m_fpr);
+ m_fpr.data());
#else
return NativeProcessFreeBSD::PtraceWrapper(PT_SETXMMREGS, m_thread.GetID(),
- &m_fpr);
+ m_fpr.data());
#endif
case DBRegSet:
return NativeProcessFreeBSD::PtraceWrapper(PT_SETDBREGS, m_thread.GetID(),
reg_info->byte_size, endian::InlHostByteOrder());
return error;
case FPRegSet:
+ reg_value.SetBytes(m_fpr.data() + reg_info->byte_offset - GetFPROffset(),
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
case XSaveRegSet:
case DBRegSet:
// legacy logic
}
switch (reg) {
-#if defined(__x86_64__)
-// the 32-bit field carries more detail, so we don't have to reinvent
-// the wheel
-#define FPR_ENV(x) ((struct envxmm32 *)m_fpr.fpr_env)->x
-#else
-#define FPR_ENV(x) ((struct envxmm *)m_fpr.xmm_env)->x
-#endif
- case lldb_fctrl_x86_64:
- reg_value = (uint16_t)FPR_ENV(en_cw);
- break;
- case lldb_fstat_x86_64:
- reg_value = (uint16_t)FPR_ENV(en_sw);
- break;
- case lldb_ftag_x86_64:
- reg_value = (uint16_t)FPR_ENV(en_tw);
- break;
- case lldb_fop_x86_64:
- reg_value = (uint16_t)FPR_ENV(en_opcode);
- break;
- case lldb_fiseg_x86_64:
- reg_value = (uint32_t)FPR_ENV(en_fcs);
- break;
- case lldb_fioff_x86_64:
- reg_value = (uint32_t)FPR_ENV(en_fip);
- break;
- case lldb_foseg_x86_64:
- reg_value = (uint32_t)FPR_ENV(en_fos);
- break;
- case lldb_fooff_x86_64:
- reg_value = (uint32_t)FPR_ENV(en_foo);
- break;
- case lldb_mxcsr_x86_64:
- reg_value = (uint32_t)FPR_ENV(en_mxcsr);
- break;
- case lldb_mxcsrmask_x86_64:
- reg_value = (uint32_t)FPR_ENV(en_mxcsr_mask);
- break;
- case lldb_st0_x86_64:
- case lldb_st1_x86_64:
- case lldb_st2_x86_64:
- case lldb_st3_x86_64:
- case lldb_st4_x86_64:
- case lldb_st5_x86_64:
- case lldb_st6_x86_64:
- case lldb_st7_x86_64:
-#if defined(__x86_64__)
- reg_value.SetBytes(&m_fpr.fpr_acc[reg - lldb_st0_x86_64],
- reg_info->byte_size, endian::InlHostByteOrder());
-#else
- reg_value.SetBytes(&m_fpr.xmm_acc[reg - lldb_st0_x86_64],
- reg_info->byte_size, endian::InlHostByteOrder());
-#endif
- break;
- case lldb_mm0_x86_64:
- case lldb_mm1_x86_64:
- case lldb_mm2_x86_64:
- case lldb_mm3_x86_64:
- case lldb_mm4_x86_64:
- case lldb_mm5_x86_64:
- case lldb_mm6_x86_64:
- case lldb_mm7_x86_64:
-#if defined(__x86_64__)
- reg_value.SetBytes(&m_fpr.fpr_acc[reg - lldb_mm0_x86_64],
- reg_info->byte_size, endian::InlHostByteOrder());
-#else
- reg_value.SetBytes(&m_fpr.xmm_acc[reg - lldb_mm0_x86_64],
- reg_info->byte_size, endian::InlHostByteOrder());
-#endif
- break;
- case lldb_xmm0_x86_64:
- case lldb_xmm1_x86_64:
- case lldb_xmm2_x86_64:
- case lldb_xmm3_x86_64:
- case lldb_xmm4_x86_64:
- case lldb_xmm5_x86_64:
- case lldb_xmm6_x86_64:
- case lldb_xmm7_x86_64:
- case lldb_xmm8_x86_64:
- case lldb_xmm9_x86_64:
- case lldb_xmm10_x86_64:
- case lldb_xmm11_x86_64:
- case lldb_xmm12_x86_64:
- case lldb_xmm13_x86_64:
- case lldb_xmm14_x86_64:
- case lldb_xmm15_x86_64:
-#if defined(__x86_64__)
- reg_value.SetBytes(&m_fpr.fpr_xacc[reg - lldb_xmm0_x86_64],
- reg_info->byte_size, endian::InlHostByteOrder());
-#else
- reg_value.SetBytes(&m_fpr.xmm_reg[reg - lldb_xmm0_x86_64],
- reg_info->byte_size, endian::InlHostByteOrder());
-#endif
- break;
case lldb_ymm0_x86_64:
case lldb_ymm1_x86_64:
case lldb_ymm2_x86_64:
reg_value.GetByteSize());
return WriteRegisterSet(set);
case FPRegSet:
+ ::memcpy(m_fpr.data() + reg_info->byte_offset - GetFPROffset(),
+ reg_value.GetBytes(), reg_value.GetByteSize());
+ return WriteRegisterSet(set);
case XSaveRegSet:
case DBRegSet:
// legacy logic
}
switch (reg) {
- case lldb_fctrl_x86_64:
- FPR_ENV(en_cw) = reg_value.GetAsUInt16();
- break;
- case lldb_fstat_x86_64:
- FPR_ENV(en_sw) = reg_value.GetAsUInt16();
- break;
- case lldb_ftag_x86_64:
- FPR_ENV(en_tw) = reg_value.GetAsUInt16();
- break;
- case lldb_fop_x86_64:
- FPR_ENV(en_opcode) = reg_value.GetAsUInt16();
- break;
- case lldb_fiseg_x86_64:
- FPR_ENV(en_fcs) = reg_value.GetAsUInt32();
- break;
- case lldb_fioff_x86_64:
- FPR_ENV(en_fip) = reg_value.GetAsUInt32();
- break;
- case lldb_foseg_x86_64:
- FPR_ENV(en_fos) = reg_value.GetAsUInt32();
- break;
- case lldb_fooff_x86_64:
- FPR_ENV(en_foo) = reg_value.GetAsUInt32();
- break;
- case lldb_mxcsr_x86_64:
- FPR_ENV(en_mxcsr) = reg_value.GetAsUInt32();
- break;
- case lldb_mxcsrmask_x86_64:
- FPR_ENV(en_mxcsr_mask) = reg_value.GetAsUInt32();
- break;
- case lldb_st0_x86_64:
- case lldb_st1_x86_64:
- case lldb_st2_x86_64:
- case lldb_st3_x86_64:
- case lldb_st4_x86_64:
- case lldb_st5_x86_64:
- case lldb_st6_x86_64:
- case lldb_st7_x86_64:
-#if defined(__x86_64__)
- ::memcpy(&m_fpr.fpr_acc[reg - lldb_st0_x86_64], reg_value.GetBytes(),
- reg_value.GetByteSize());
-#else
- ::memcpy(&m_fpr.xmm_acc[reg - lldb_st0_x86_64], reg_value.GetBytes(),
- reg_value.GetByteSize());
-#endif
- break;
- case lldb_mm0_x86_64:
- case lldb_mm1_x86_64:
- case lldb_mm2_x86_64:
- case lldb_mm3_x86_64:
- case lldb_mm4_x86_64:
- case lldb_mm5_x86_64:
- case lldb_mm6_x86_64:
- case lldb_mm7_x86_64:
-#if defined(__x86_64__)
- ::memcpy(&m_fpr.fpr_acc[reg - lldb_mm0_x86_64], reg_value.GetBytes(),
- reg_value.GetByteSize());
-#else
- ::memcpy(&m_fpr.xmm_acc[reg - lldb_mm0_x86_64], reg_value.GetBytes(),
- reg_value.GetByteSize());
-#endif
- break;
- case lldb_xmm0_x86_64:
- case lldb_xmm1_x86_64:
- case lldb_xmm2_x86_64:
- case lldb_xmm3_x86_64:
- case lldb_xmm4_x86_64:
- case lldb_xmm5_x86_64:
- case lldb_xmm6_x86_64:
- case lldb_xmm7_x86_64:
- case lldb_xmm8_x86_64:
- case lldb_xmm9_x86_64:
- case lldb_xmm10_x86_64:
- case lldb_xmm11_x86_64:
- case lldb_xmm12_x86_64:
- case lldb_xmm13_x86_64:
- case lldb_xmm14_x86_64:
- case lldb_xmm15_x86_64:
-#if defined(__x86_64__)
- ::memcpy(&m_fpr.fpr_xacc[reg - lldb_xmm0_x86_64], reg_value.GetBytes(),
- reg_value.GetByteSize());
-#else
- ::memcpy(&m_fpr.xmm_reg[reg - lldb_xmm0_x86_64], reg_value.GetBytes(),
- reg_value.GetByteSize());
-#endif
- break;
case lldb_ymm0_x86_64:
case lldb_ymm1_x86_64:
case lldb_ymm2_x86_64:
return res.ToError();
}
+size_t NativeRegisterContextFreeBSD_x86_64::GetFPROffset() const {
+ uint32_t regno;
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::x86:
+ regno = lldb_fctrl_i386;
+ break;
+ case llvm::Triple::x86_64:
+ regno = lldb_fctrl_x86_64;
+ break;
+ default:
+ llvm_unreachable("Unhandled target architecture.");
+ }
+
+ return GetRegisterInfoInterface().GetRegisterInfo()[regno].byte_offset;
+}
+
#endif // defined(__x86_64__)
return {info.byte_offset, info.byte_size};
}
+#define EXPECT_OFF(regname, offset, size) \
+ EXPECT_THAT(GetRegParams(reg_ctx, lldb_##regname), \
+ ::testing::Pair(offset + base_offset, size))
+
#if defined(__x86_64__)
#define EXPECT_GPR_X86_64(regname) \
EXPECT_GPR_X86_64(rflags);
EXPECT_GPR_X86_64(rsp);
EXPECT_GPR_X86_64(ss);
+
+ // fctrl is the first FPR field, it is used to determine offset of the whole
+ // FPR struct
+ size_t base_offset = reg_ctx.GetRegisterInfo()[lldb_fctrl_x86_64].byte_offset;
+
+ // assert against FXSAVE struct
+ EXPECT_OFF(fctrl_x86_64, 0x00, 2);
+ EXPECT_OFF(fstat_x86_64, 0x02, 2);
+ // TODO: This is a known bug, abridged ftag should is 8 bits in length.
+ EXPECT_OFF(ftag_x86_64, 0x04, 2);
+ EXPECT_OFF(fop_x86_64, 0x06, 2);
+ // NB: Technically fiseg/foseg are 16-bit long and the higher 16 bits
+ // are reserved. However, we use them to access/recombine 64-bit FIP/FDP.
+ EXPECT_OFF(fioff_x86_64, 0x08, 4);
+ EXPECT_OFF(fiseg_x86_64, 0x0C, 4);
+ EXPECT_OFF(fooff_x86_64, 0x10, 4);
+ EXPECT_OFF(foseg_x86_64, 0x14, 4);
+ EXPECT_OFF(mxcsr_x86_64, 0x18, 4);
+ EXPECT_OFF(mxcsrmask_x86_64, 0x1C, 4);
+ EXPECT_OFF(st0_x86_64, 0x20, 10);
+ EXPECT_OFF(st1_x86_64, 0x30, 10);
+ EXPECT_OFF(st2_x86_64, 0x40, 10);
+ EXPECT_OFF(st3_x86_64, 0x50, 10);
+ EXPECT_OFF(st4_x86_64, 0x60, 10);
+ EXPECT_OFF(st5_x86_64, 0x70, 10);
+ EXPECT_OFF(st6_x86_64, 0x80, 10);
+ EXPECT_OFF(st7_x86_64, 0x90, 10);
+ EXPECT_OFF(mm0_x86_64, 0x20, 8);
+ EXPECT_OFF(mm1_x86_64, 0x30, 8);
+ EXPECT_OFF(mm2_x86_64, 0x40, 8);
+ EXPECT_OFF(mm3_x86_64, 0x50, 8);
+ EXPECT_OFF(mm4_x86_64, 0x60, 8);
+ EXPECT_OFF(mm5_x86_64, 0x70, 8);
+ EXPECT_OFF(mm6_x86_64, 0x80, 8);
+ EXPECT_OFF(mm7_x86_64, 0x90, 8);
+ EXPECT_OFF(xmm0_x86_64, 0xA0, 16);
+ EXPECT_OFF(xmm1_x86_64, 0xB0, 16);
+ EXPECT_OFF(xmm2_x86_64, 0xC0, 16);
+ EXPECT_OFF(xmm3_x86_64, 0xD0, 16);
+ EXPECT_OFF(xmm4_x86_64, 0xE0, 16);
+ EXPECT_OFF(xmm5_x86_64, 0xF0, 16);
+ EXPECT_OFF(xmm6_x86_64, 0x100, 16);
+ EXPECT_OFF(xmm7_x86_64, 0x110, 16);
+ EXPECT_OFF(xmm8_x86_64, 0x120, 16);
+ EXPECT_OFF(xmm9_x86_64, 0x130, 16);
+ EXPECT_OFF(xmm10_x86_64, 0x140, 16);
+ EXPECT_OFF(xmm11_x86_64, 0x150, 16);
+ EXPECT_OFF(xmm12_x86_64, 0x160, 16);
+ EXPECT_OFF(xmm13_x86_64, 0x170, 16);
+ EXPECT_OFF(xmm14_x86_64, 0x180, 16);
+ EXPECT_OFF(xmm15_x86_64, 0x190, 16);
}
#endif // defined(__x86_64__)
EXPECT_GPR_I386(esp);
EXPECT_GPR_I386(ss);
EXPECT_GPR_I386(gs);
+
+ // fctrl is the first FPR field, it is used to determine offset of the whole
+ // FPR struct
+ size_t base_offset = reg_ctx.GetRegisterInfo()[lldb_fctrl_i386].byte_offset;
+
+ // assert against FXSAVE struct
+ EXPECT_OFF(fctrl_i386, 0x00, 2);
+ EXPECT_OFF(fstat_i386, 0x02, 2);
+ // TODO: This is a known bug, abridged ftag should is 8 bits in length.
+ EXPECT_OFF(ftag_i386, 0x04, 2);
+ EXPECT_OFF(fop_i386, 0x06, 2);
+ // NB: Technically fiseg/foseg are 16-bit long and the higher 16 bits
+ // are reserved. However, we use them to access/recombine 64-bit FIP/FDP.
+ EXPECT_OFF(fioff_i386, 0x08, 4);
+ EXPECT_OFF(fiseg_i386, 0x0C, 4);
+ EXPECT_OFF(fooff_i386, 0x10, 4);
+ EXPECT_OFF(foseg_i386, 0x14, 4);
+ EXPECT_OFF(mxcsr_i386, 0x18, 4);
+ EXPECT_OFF(mxcsrmask_i386, 0x1C, 4);
+ EXPECT_OFF(st0_i386, 0x20, 10);
+ EXPECT_OFF(st1_i386, 0x30, 10);
+ EXPECT_OFF(st2_i386, 0x40, 10);
+ EXPECT_OFF(st3_i386, 0x50, 10);
+ EXPECT_OFF(st4_i386, 0x60, 10);
+ EXPECT_OFF(st5_i386, 0x70, 10);
+ EXPECT_OFF(st6_i386, 0x80, 10);
+ EXPECT_OFF(st7_i386, 0x90, 10);
+ EXPECT_OFF(mm0_i386, 0x20, 8);
+ EXPECT_OFF(mm1_i386, 0x30, 8);
+ EXPECT_OFF(mm2_i386, 0x40, 8);
+ EXPECT_OFF(mm3_i386, 0x50, 8);
+ EXPECT_OFF(mm4_i386, 0x60, 8);
+ EXPECT_OFF(mm5_i386, 0x70, 8);
+ EXPECT_OFF(mm6_i386, 0x80, 8);
+ EXPECT_OFF(mm7_i386, 0x90, 8);
+ EXPECT_OFF(xmm0_i386, 0xA0, 16);
+ EXPECT_OFF(xmm1_i386, 0xB0, 16);
+ EXPECT_OFF(xmm2_i386, 0xC0, 16);
+ EXPECT_OFF(xmm3_i386, 0xD0, 16);
+ EXPECT_OFF(xmm4_i386, 0xE0, 16);
+ EXPECT_OFF(xmm5_i386, 0xF0, 16);
+ EXPECT_OFF(xmm6_i386, 0x100, 16);
+ EXPECT_OFF(xmm7_i386, 0x110, 16);
}
#endif // defined(__i386__) || defined(__x86_64__)