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__) mydir = TestBase.compute_mydir(__file__)
@expectedFailurei386 @expectedFailureAll(oslist=["macosx","freebsd"], archs=["i386"])
@expectedFailureWindows("llvm.org/pr24778") @expectedFailureWindows("llvm.org/pr24778")
@add_test_categories(['pyapi']) @add_test_categories(['pyapi'])
def test_with_python(self): def test_with_python(self):

View File

@ -327,6 +327,9 @@ namespace
#ifndef NT_X86_XSTATE #ifndef NT_X86_XSTATE
#define NT_X86_XSTATE 0x202 #define NT_X86_XSTATE 0x202
#endif #endif
#ifndef NT_PRXFPREG
#define NT_PRXFPREG 0x46e62b7f
#endif
NativeRegisterContextLinux* NativeRegisterContextLinux*
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, 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::FPRType
NativeRegisterContextLinux_x86_64::GetFPRType () const NativeRegisterContextLinux_x86_64::GetFPRType () const
{ {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
if (m_fpr_type == eFPRTypeNotValid) if (m_fpr_type == eFPRTypeNotValid)
{ {
// TODO: Use assembly to call cpuid on the inferior and query ebx or ecx. // 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. // Fall back to general floating point with no AVX support.
m_fpr_type = eFPRTypeFXSAVE; 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; return m_fpr_type;
} }
@ -868,10 +878,24 @@ Error
NativeRegisterContextLinux_x86_64::WriteFPR() NativeRegisterContextLinux_x86_64::WriteFPR()
{ {
const FPRType fpr_type = GetFPRType (); const FPRType fpr_type = GetFPRType ();
const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture();
switch (fpr_type) switch (fpr_type)
{ {
case FPRType::eFPRTypeFXSAVE: 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: case FPRType::eFPRTypeXSAVE:
return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
default: default:
@ -980,10 +1004,24 @@ Error
NativeRegisterContextLinux_x86_64::ReadFPR () NativeRegisterContextLinux_x86_64::ReadFPR ()
{ {
const FPRType fpr_type = GetFPRType (); const FPRType fpr_type = GetFPRType ();
const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture();
switch (fpr_type) switch (fpr_type)
{ {
case FPRType::eFPRTypeFXSAVE: 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: case FPRType::eFPRTypeXSAVE:
return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
default: default: