Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -104,6 +104,56 @@ # 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) Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/fpr_sse.cpp @@ -0,0 +1,38 @@ +// 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; +} Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_i386.h =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -18,6 +18,8 @@ size_t GetGPRSize() const override; + size_t GetFXSAVEOffset() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; uint32_t GetRegisterCount() const override; Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -111,6 +111,10 @@ 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: Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -18,6 +18,8 @@ size_t GetGPRSize() const override; + size_t GetFXSAVEOffset() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; uint32_t GetRegisterCount() const override; Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -179,6 +179,11 @@ 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 * RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const { return &d_register_infos; Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -38,6 +38,8 @@ virtual size_t GetGPRSize(); + virtual size_t GetFXSAVEOffset(); + virtual unsigned GetRegisterSize(unsigned reg); virtual unsigned GetRegisterOffset(unsigned reg); Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -419,6 +419,10 @@ 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. Index: lldb/trunk/source/Plugins/Process/Utility/RegisterInfoInterface.h =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ lldb/trunk/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -29,6 +29,8 @@ 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 Index: lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -400,7 +400,8 @@ NT_TASKSTRUCT, NT_PLATFORM, NT_AUXV, - NT_FILE = 0x46494c45 + NT_FILE = 0x46494c45, + NT_PRXFPREG = 0x46e62b7f, }; namespace FREEBSD { @@ -552,7 +553,11 @@ 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; @@ -586,6 +591,11 @@ default: break; } + } else if (note.n_name == "LINUX") { + switch (note.n_type) { + case NT_PRXFPREG: + thread_data->fpregset = note_data; + } } offset += note_size; Index: lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h =================================================================== --- lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h +++ lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h @@ -24,8 +24,6 @@ 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; @@ -48,7 +46,8 @@ bool WriteFPR() override; private: - uint8_t *m_gpregset; + std::unique_ptr m_gpregset; + std::unique_ptr m_fpregset; }; #endif // liblldb_RegisterContextCorePOSIX_x86_64_h_ Index: lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -21,18 +21,27 @@ 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(); + + 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(); } -RegisterContextCorePOSIX_x86_64::~RegisterContextCorePOSIX_x86_64() { - delete[] m_gpregset; +bool RegisterContextCorePOSIX_x86_64::ReadGPR() { + return m_gpregset != nullptr; } -bool RegisterContextCorePOSIX_x86_64::ReadGPR() { return m_gpregset != NULL; } - -bool RegisterContextCorePOSIX_x86_64::ReadFPR() { return false; } +bool RegisterContextCorePOSIX_x86_64::ReadFPR() { + return m_fpregset != nullptr; +} bool RegisterContextCorePOSIX_x86_64::WriteGPR() { assert(0); @@ -46,15 +55,27 @@ 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(