# same pid
self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions)
+ @skipIf(oslist=['windows'])
+ @skipIf(triple='^mips')
+ def test_FPR_SSE(self):
+ # check x86_64 core file
+ target = self.dbg.CreateTarget(None)
+ self.assertTrue(target, VALID_TARGET)
+ process = target.LoadCore("linux-fpr_sse_x86_64.core")
+
+ values = {}
+ values["fctrl"] = "0x037f"
+ values["fstat"] = "0x0000"
+ values["ftag"] = "0xff"
+ values["fop"] = "0x0000"
+ values["fiseg"] = "0x00000000"
+ values["fioff"] = "0x0040011e"
+ values["foseg"] = "0x00000000"
+ values["fooff"] = "0x00000000"
+ values["mxcsr"] = "0x00001f80"
+ values["mxcsrmask"] = "0x0000ffff"
+ values["st0"] = "{0x99 0xf7 0xcf 0xfb 0x84 0x9a 0x20 0x9a 0xfd 0x3f}"
+ values["st1"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x3f}"
+ values["st2"] = "{0xfe 0x8a 0x1b 0xcd 0x4b 0x78 0x9a 0xd4 0x00 0x40}"
+ values["st3"] = "{0xac 0x79 0xcf 0xd1 0xf7 0x17 0x72 0xb1 0xfe 0x3f}"
+ values["st4"] = "{0xbc 0xf0 0x17 0x5c 0x29 0x3b 0xaa 0xb8 0xff 0x3f}"
+ values["st5"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x3f}"
+ values["st6"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
+ values["st7"] = "{0x35 0xc2 0x68 0x21 0xa2 0xda 0x0f 0xc9 0x00 0x40}"
+ values["xmm0"] = "{0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46}"
+ values["xmm1"] = "{0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64}"
+ values["xmm2"] = "{0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7}"
+ values["xmm3"] = "{0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25}"
+ values["xmm4"] = "{0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4}"
+ values["xmm5"] = "{0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b}"
+ values["xmm6"] = "{0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f}"
+ values["xmm7"] = "{0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd}"
+
+ for regname, value in values.iteritems():
+ self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)])
+
+
+ # now check i386 core file
+ target = self.dbg.CreateTarget(None)
+ self.assertTrue(target, VALID_TARGET)
+ process = target.LoadCore("linux-fpr_sse_i386.core")
+
+ values["fioff"] = "0x080480cc"
+
+ for regname, value in values.iteritems():
+ self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)])
+
def check_memory_regions(self, process, region_count):
region_list = process.GetMemoryRegions()
self.assertEqual(region_list.GetSize(), region_count)
--- /dev/null
+// fpr_sse_x86_64.core was generated with:
+// ./make-core.sh fpr_sse.cpp
+//
+// fpr_sse_i386.core was generated with:
+// export CFLAGS=-m32
+// ./make-core.sh fpr_sse.cpp
+
+void _start(void) {
+ __asm__("fldpi;"
+ "fldz;"
+ "fld1;"
+ "fldl2e;"
+ "fldln2;"
+ "fldl2t;"
+ "fld1;"
+ "fldlg2;");
+
+ unsigned int values[8] = {
+ 0x46643129, 0x6486ed9c, 0xd71fc207, 0x254820a2,
+ 0xc4a85aeb, 0x0b204149, 0x4f8bf1f8, 0xcd30f113,
+ };
+
+ __asm__("vbroadcastss %0, %%xmm0;"
+ "vbroadcastss %1, %%xmm1;"
+ "vbroadcastss %2, %%xmm2;"
+ "vbroadcastss %3, %%xmm3;"
+ "vbroadcastss %4, %%xmm4;"
+ "vbroadcastss %5, %%xmm5;"
+ "vbroadcastss %6, %%xmm6;"
+ "vbroadcastss %7, %%xmm7;"
+
+ ::"m"(values[0]),
+ "m"(values[1]), "m"(values[2]), "m"(values[3]), "m"(values[4]),
+ "m"(values[5]), "m"(values[6]), "m"(values[7]));
+
+ volatile int *a = 0;
+ *a = 0;
+}
size_t RegisterContextLinux_i386::GetGPRSize() const { return sizeof(GPR); }
+size_t RegisterContextLinux_i386::GetFXSAVEOffset() const {
+ return (LLVM_EXTENSION offsetof(UserArea, i387));
+}
+
const RegisterInfo *RegisterContextLinux_i386::GetRegisterInfo() const {
switch (m_target_arch.GetMachine()) {
case llvm::Triple::x86:
size_t GetGPRSize() const override;
+ size_t GetFXSAVEOffset() const override;
+
const lldb_private::RegisterInfo *GetRegisterInfo() const override;
uint32_t GetRegisterCount() const override;
size_t RegisterContextLinux_x86_64::GetGPRSize() const { return sizeof(GPR); }
+size_t RegisterContextLinux_x86_64::GetFXSAVEOffset() const {
+ return (LLVM_EXTENSION offsetof(UserArea, fpr) +
+ LLVM_EXTENSION offsetof(FPR, xstate));
+}
+
const std::vector<lldb_private::RegisterInfo> *
RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const {
return &d_register_infos;
size_t GetGPRSize() const override;
+ size_t GetFXSAVEOffset() const override;
+
const lldb_private::RegisterInfo *GetRegisterInfo() const override;
uint32_t GetRegisterCount() const override;
return m_register_info_ap->GetGPRSize();
}
+size_t RegisterContextPOSIX_x86::GetFXSAVEOffset() {
+ return m_register_info_ap->GetFXSAVEOffset();
+}
+
const RegisterInfo *RegisterContextPOSIX_x86::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
// specialized.
virtual size_t GetGPRSize();
+ virtual size_t GetFXSAVEOffset();
+
virtual unsigned GetRegisterSize(unsigned reg);
virtual unsigned GetRegisterOffset(unsigned reg);
virtual size_t GetGPRSize() const = 0;
+ virtual size_t GetFXSAVEOffset() const { return 0; }
+
virtual const lldb_private::RegisterInfo *GetRegisterInfo() const = 0;
// Returns the number of registers including the user registers and the
NT_TASKSTRUCT,
NT_PLATFORM,
NT_AUXV,
- NT_FILE = 0x46494c45
+ NT_FILE = 0x46494c45,
+ NT_PRXFPREG = 0x46e62b7f,
};
namespace FREEBSD {
thread_data->gpregset = DataExtractor(note_data, header_size, len);
break;
case NT_FPREGSET:
- thread_data->fpregset = note_data;
+ // In a i386 core file NT_FPREGSET is present, but it's not the result
+ // of the FXSAVE instruction like in 64 bit files.
+ // The result from FXSAVE is in NT_PRXFPREG for i386 core files
+ if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64)
+ thread_data->fpregset = note_data;
break;
case NT_PRPSINFO:
have_prpsinfo = true;
default:
break;
}
+ } else if (note.n_name == "LINUX") {
+ switch (note.n_type) {
+ case NT_PRXFPREG:
+ thread_data->fpregset = note_data;
+ }
}
offset += note_size;
size_t size, len;
size = GetGPRSize();
- m_gpregset = new uint8_t[size];
- len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
- assert(len == size);
-}
+ m_gpregset.reset(new uint8_t[size]);
+ len =
+ gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset.get());
+ if (len != size)
+ m_gpregset.reset();
-RegisterContextCorePOSIX_x86_64::~RegisterContextCorePOSIX_x86_64() {
- delete[] m_gpregset;
+ size = sizeof(FXSAVE);
+ m_fpregset.reset(new uint8_t[size]);
+ len =
+ fpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_fpregset.get());
+ if (len != size)
+ m_fpregset.reset();
}
-bool RegisterContextCorePOSIX_x86_64::ReadGPR() { return m_gpregset != NULL; }
+bool RegisterContextCorePOSIX_x86_64::ReadGPR() {
+ return m_gpregset != nullptr;
+}
-bool RegisterContextCorePOSIX_x86_64::ReadFPR() { return false; }
+bool RegisterContextCorePOSIX_x86_64::ReadFPR() {
+ return m_fpregset != nullptr;
+}
bool RegisterContextCorePOSIX_x86_64::WriteGPR() {
assert(0);
bool RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &value) {
- switch (reg_info->byte_size) {
- case 4:
- value = *(uint32_t *)(m_gpregset + reg_info->byte_offset);
- return true;
- case 8:
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
+ const uint8_t *src;
+ size_t offset;
+ const size_t fxsave_offset = reg_info->byte_offset - GetFXSAVEOffset();
+ // make the offset relative to the beginning of the FXSAVE structure
+ // because this is the data that we have (not the entire UserArea)
+
+ if (m_gpregset && reg_info->byte_offset < GetGPRSize()) {
+ src = m_gpregset.get();
+ offset = reg_info->byte_offset;
+ } else if (m_fpregset && fxsave_offset < sizeof(FXSAVE)) {
+ src = m_fpregset.get();
+ offset = fxsave_offset;
+ } else {
+ return false;
}
- return false;
+
+ Error error;
+ value.SetFromMemoryData(reg_info, src + offset, reg_info->byte_size,
+ lldb::eByteOrderLittle, error);
+
+ return error.Success();
}
bool RegisterContextCorePOSIX_x86_64::ReadAllRegisterValues(
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_x86_64() override;
-
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value) override;
bool WriteFPR() override;
private:
- uint8_t *m_gpregset;
+ std::unique_ptr<uint8_t[]> m_gpregset;
+ std::unique_ptr<uint8_t[]> m_fpregset;
};
#endif // liblldb_RegisterContextCorePOSIX_x86_64_h_