PTRACE ABI to read FXSAVE area for 32-bit inferior

Summary:
 - Problem occurs when:
    -- 32-bit inferiors run on x86_32 machine and
       the architecture doesn't have AVX feature

    -- This causes FPRType to be set to eFPRTypeFXSAVE

    -- PTRACE_GETFPREGS was being used to read FXSAVE area

    -- For 32-bit inferiors running on x86_32 machine,
       PTRACE_GETFPREGS reads FSAVE area and not FXSAVE area

 - Changed ptrace API to PTRACE_GETREGSET for 32-bit inferiors
    -- This reads FPR data in FXSAVE format.
    -- For 64-bit inferiors, no change has been made.

 - Modified XFAIL for TestReturnValue.py
    -- Earlier, this test was passing for Linux OS
    -- Now, it passes for Android OS as well

Change-Id: Ieed72bc969b79516fc7b263b32493aa1e7a1a2ac
Signed-off-by: Abhishek Aggarwal <abhishek.a.aggarwal@intel.com>

Reviewers: ovyalov, jingham, lldb-commits, tberghammer, labath

Subscribers: jevinskie, labath, tberghammer, danalbert

Differential Revision: http://reviews.llvm.org/D15042

llvm-svn: 254499
This commit is contained in:
Abhishek Aggarwal 2015-12-02 09:40:17 +00:00
parent aed1e03888
commit 296e063d8f
2 changed files with 42 additions and 4 deletions

View File

@ -16,7 +16,7 @@ class ReturnValueTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@expectedFailurei386
@expectedFailureAll(oslist=["macosx","freebsd"], archs=["i386"])
@expectedFailureWindows("llvm.org/pr24778")
@add_test_categories(['pyapi'])
def test_with_python(self):

View File

@ -327,6 +327,9 @@ namespace
#ifndef NT_X86_XSTATE
#define NT_X86_XSTATE 0x202
#endif
#ifndef NT_PRXFPREG
#define NT_PRXFPREG 0x46e62b7f
#endif
NativeRegisterContextLinux*
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
@ -832,6 +835,7 @@ NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const
NativeRegisterContextLinux_x86_64::FPRType
NativeRegisterContextLinux_x86_64::GetFPRType () const
{
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
if (m_fpr_type == eFPRTypeNotValid)
{
// TODO: Use assembly to call cpuid on the inferior and query ebx or ecx.
@ -842,9 +846,15 @@ NativeRegisterContextLinux_x86_64::GetFPRType () const
{
// Fall back to general floating point with no AVX support.
m_fpr_type = eFPRTypeFXSAVE;
// Check if FXSAVE area can be read.
if (const_cast<NativeRegisterContextLinux_x86_64*>(this)->ReadFPR().Fail())
{
if (log)
log->Printf("NativeRegisterContextLinux_x86_64::%s ptrace APIs failed to read XSAVE/FXSAVE area", __FUNCTION__);
}
}
}
return m_fpr_type;
}
@ -868,10 +878,24 @@ Error
NativeRegisterContextLinux_x86_64::WriteFPR()
{
const FPRType fpr_type = GetFPRType ();
const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture();
switch (fpr_type)
{
case FPRType::eFPRTypeFXSAVE:
return NativeRegisterContextLinux::WriteFPR();
// For 32-bit inferiors on x86_32/x86_64 architectures,
// FXSAVE area can be written using PTRACE_SETREGSET ptrace api
// For 64-bit inferiors on x86_64 architectures,
// FXSAVE area can be written using PTRACE_SETFPREGS ptrace api
switch (target_arch.GetMachine ())
{
case llvm::Triple::x86:
return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG);
case llvm::Triple::x86_64:
return NativeRegisterContextLinux::WriteFPR();
default:
assert(false && "Unhandled target architecture.");
break;
}
case FPRType::eFPRTypeXSAVE:
return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
default:
@ -980,10 +1004,24 @@ Error
NativeRegisterContextLinux_x86_64::ReadFPR ()
{
const FPRType fpr_type = GetFPRType ();
const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture();
switch (fpr_type)
{
case FPRType::eFPRTypeFXSAVE:
return NativeRegisterContextLinux::ReadFPR();
// For 32-bit inferiors on x86_32/x86_64 architectures,
// FXSAVE area can be read using PTRACE_GETREGSET ptrace api
// For 64-bit inferiors on x86_64 architectures,
// FXSAVE area can be read using PTRACE_GETFPREGS ptrace api
switch (target_arch.GetMachine ())
{
case llvm::Triple::x86:
return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG);
case llvm::Triple::x86_64:
return NativeRegisterContextLinux::ReadFPR();
default:
assert(false && "Unhandled target architecture.");
break;
}
case FPRType::eFPRTypeXSAVE:
return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
default: