mgorny updated this revision to Diff 304479.
mgorny added a comment.
Rename `ASSERT_FPR` to `ASSERT_OFF` since it's a more generic offset-based
assert.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D91248/new/
https://reviews.llvm.org/D91248
Files:
lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
lldb/unittests/Process/FreeBSD/RegisterContextFreeBSDTests.cpp
Index: lldb/unittests/Process/FreeBSD/RegisterContextFreeBSDTests.cpp
===================================================================
--- lldb/unittests/Process/FreeBSD/RegisterContextFreeBSDTests.cpp
+++ lldb/unittests/Process/FreeBSD/RegisterContextFreeBSDTests.cpp
@@ -26,10 +26,13 @@
#define ASSERT_REG(regname, offset, size) \
{ \
const RegisterInfo *reg_info = ®_ctx.GetRegisterInfo()[lldb_##regname]; \
- EXPECT_EQ(reg_info->byte_offset, offset); \
- EXPECT_EQ(reg_info->byte_size, size); \
+ EXPECT_EQ(reg_info->byte_offset, static_cast<size_t>(offset)); \
+ EXPECT_EQ(reg_info->byte_size, static_cast<size_t>(size)); \
}
+#define ASSERT_OFF(regname, offset, size) \
+ ASSERT_REG(regname, offset + base_offset, size)
+
#if defined(__x86_64__)
#define ASSERT_GPR_X86_64(regname) \
@@ -64,6 +67,57 @@
ASSERT_GPR_X86_64(rflags);
ASSERT_GPR_X86_64(rsp);
ASSERT_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
+ ASSERT_OFF(fctrl_x86_64, 0x00, 2);
+ ASSERT_OFF(fstat_x86_64, 0x02, 2);
+ // TODO: This is a known bug, abridged ftag should is 8 bits in length.
+ ASSERT_OFF(ftag_x86_64, 0x04, 2);
+ ASSERT_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.
+ ASSERT_OFF(fioff_x86_64, 0x08, 4);
+ ASSERT_OFF(fiseg_x86_64, 0x0C, 4);
+ ASSERT_OFF(fooff_x86_64, 0x10, 4);
+ ASSERT_OFF(foseg_x86_64, 0x14, 4);
+ ASSERT_OFF(mxcsr_x86_64, 0x18, 4);
+ ASSERT_OFF(mxcsrmask_x86_64, 0x1C, 4);
+ ASSERT_OFF(st0_x86_64, 0x20, 10);
+ ASSERT_OFF(st1_x86_64, 0x30, 10);
+ ASSERT_OFF(st2_x86_64, 0x40, 10);
+ ASSERT_OFF(st3_x86_64, 0x50, 10);
+ ASSERT_OFF(st4_x86_64, 0x60, 10);
+ ASSERT_OFF(st5_x86_64, 0x70, 10);
+ ASSERT_OFF(st6_x86_64, 0x80, 10);
+ ASSERT_OFF(st7_x86_64, 0x90, 10);
+ ASSERT_OFF(mm0_x86_64, 0x20, 8);
+ ASSERT_OFF(mm1_x86_64, 0x30, 8);
+ ASSERT_OFF(mm2_x86_64, 0x40, 8);
+ ASSERT_OFF(mm3_x86_64, 0x50, 8);
+ ASSERT_OFF(mm4_x86_64, 0x60, 8);
+ ASSERT_OFF(mm5_x86_64, 0x70, 8);
+ ASSERT_OFF(mm6_x86_64, 0x80, 8);
+ ASSERT_OFF(mm7_x86_64, 0x90, 8);
+ ASSERT_OFF(xmm0_x86_64, 0xA0, 16);
+ ASSERT_OFF(xmm1_x86_64, 0xB0, 16);
+ ASSERT_OFF(xmm2_x86_64, 0xC0, 16);
+ ASSERT_OFF(xmm3_x86_64, 0xD0, 16);
+ ASSERT_OFF(xmm4_x86_64, 0xE0, 16);
+ ASSERT_OFF(xmm5_x86_64, 0xF0, 16);
+ ASSERT_OFF(xmm6_x86_64, 0x100, 16);
+ ASSERT_OFF(xmm7_x86_64, 0x110, 16);
+ ASSERT_OFF(xmm8_x86_64, 0x120, 16);
+ ASSERT_OFF(xmm9_x86_64, 0x130, 16);
+ ASSERT_OFF(xmm10_x86_64, 0x140, 16);
+ ASSERT_OFF(xmm11_x86_64, 0x150, 16);
+ ASSERT_OFF(xmm12_x86_64, 0x160, 16);
+ ASSERT_OFF(xmm13_x86_64, 0x170, 16);
+ ASSERT_OFF(xmm14_x86_64, 0x180, 16);
+ ASSERT_OFF(xmm15_x86_64, 0x190, 16);
}
#endif
@@ -96,5 +150,48 @@
ASSERT_GPR_I386(esp);
ASSERT_GPR_I386(ss);
ASSERT_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
+ ASSERT_OFF(fctrl_i386, 0x00, 2);
+ ASSERT_OFF(fstat_i386, 0x02, 2);
+ // TODO: This is a known bug, abridged ftag should is 8 bits in length.
+ ASSERT_OFF(ftag_i386, 0x04, 2);
+ ASSERT_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.
+ ASSERT_OFF(fioff_i386, 0x08, 4);
+ ASSERT_OFF(fiseg_i386, 0x0C, 4);
+ ASSERT_OFF(fooff_i386, 0x10, 4);
+ ASSERT_OFF(foseg_i386, 0x14, 4);
+ ASSERT_OFF(mxcsr_i386, 0x18, 4);
+ ASSERT_OFF(mxcsrmask_i386, 0x1C, 4);
+ ASSERT_OFF(st0_i386, 0x20, 10);
+ ASSERT_OFF(st1_i386, 0x30, 10);
+ ASSERT_OFF(st2_i386, 0x40, 10);
+ ASSERT_OFF(st3_i386, 0x50, 10);
+ ASSERT_OFF(st4_i386, 0x60, 10);
+ ASSERT_OFF(st5_i386, 0x70, 10);
+ ASSERT_OFF(st6_i386, 0x80, 10);
+ ASSERT_OFF(st7_i386, 0x90, 10);
+ ASSERT_OFF(mm0_i386, 0x20, 8);
+ ASSERT_OFF(mm1_i386, 0x30, 8);
+ ASSERT_OFF(mm2_i386, 0x40, 8);
+ ASSERT_OFF(mm3_i386, 0x50, 8);
+ ASSERT_OFF(mm4_i386, 0x60, 8);
+ ASSERT_OFF(mm5_i386, 0x70, 8);
+ ASSERT_OFF(mm6_i386, 0x80, 8);
+ ASSERT_OFF(mm7_i386, 0x90, 8);
+ ASSERT_OFF(xmm0_i386, 0xA0, 16);
+ ASSERT_OFF(xmm1_i386, 0xB0, 16);
+ ASSERT_OFF(xmm2_i386, 0xC0, 16);
+ ASSERT_OFF(xmm3_i386, 0xD0, 16);
+ ASSERT_OFF(xmm4_i386, 0xE0, 16);
+ ASSERT_OFF(xmm5_i386, 0xF0, 16);
+ ASSERT_OFF(xmm6_i386, 0x100, 16);
+ ASSERT_OFF(xmm7_i386, 0x110, 16);
}
#endif
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
@@ -70,11 +70,7 @@
// Private member variables.
std::array<uint8_t, sizeof(struct reg)> m_gpr;
-#if defined(__x86_64__)
- struct fpreg m_fpr;
-#else
- struct xmmreg m_fpr;
-#endif
+ std::array<uint8_t, 512> m_fpr; // FXSAVE
struct dbreg m_dbr;
std::vector<uint8_t> m_xsave;
std::array<uint32_t, MaxXSaveSet + 1> m_xsave_offsets;
@@ -84,6 +80,8 @@
Status ReadRegisterSet(uint32_t set);
Status WriteRegisterSet(uint32_t set);
+
+ size_t GetFPROffset() const;
};
} // namespace process_freebsd
Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
===================================================================
--- lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
+++ lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
@@ -248,7 +248,7 @@
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());
}
@@ -278,53 +278,6 @@
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:
@@ -403,10 +356,10 @@
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(),
@@ -444,10 +397,10 @@
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(),
@@ -501,6 +454,9 @@
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
@@ -518,99 +474,6 @@
}
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:
@@ -701,6 +564,9 @@
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
@@ -718,92 +584,6 @@
}
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:
@@ -933,4 +713,20 @@
return res.ToError();
}
+size_t NativeRegisterContextFreeBSD_x86_64::GetFPROffset() const {
+ int 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__)
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits