diff options
Diffstat (limited to 'gdb/x86-linux-nat.c')
-rw-r--r-- | gdb/x86-linux-nat.c | 91 |
1 files changed, 77 insertions, 14 deletions
diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c index 872e27e..b39d05c 100644 --- a/gdb/x86-linux-nat.c +++ b/gdb/x86-linux-nat.c @@ -42,7 +42,6 @@ #include "nat/x86-linux.h" #include "nat/x86-linux-dregs.h" #include "nat/linux-ptrace.h" -#include "nat/x86-linux-tdesc.h" /* linux_nat_target::low_new_fork implementation. */ @@ -97,26 +96,90 @@ x86_linux_nat_target::post_startup_inferior (ptid_t ptid) const struct target_desc * x86_linux_nat_target::read_description () { - static uint64_t xcr0_storage; + int tid; + int is_64bit = 0; +#ifdef __x86_64__ + int is_x32; +#endif + static uint64_t xcr0; + uint64_t xcr0_features_bits; if (inferior_ptid == null_ptid) return this->beneath ()->read_description (); - int tid = inferior_ptid.pid (); + tid = inferior_ptid.pid (); + +#ifdef __x86_64__ + + x86_linux_arch_size arch_size = x86_linux_ptrace_get_arch_size (tid); + is_64bit = arch_size.is_64bit (); + is_x32 = arch_size.is_x32 (); + +#elif HAVE_PTRACE_GETFPXREGS + if (have_ptrace_getfpxregs == -1) + { + elf_fpxregset_t fpxregs; + + if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) + { + have_ptrace_getfpxregs = 0; + have_ptrace_getregset = TRIBOOL_FALSE; + return i386_linux_read_description (X86_XSTATE_X87_MASK); + } + } +#endif + + if (have_ptrace_getregset == TRIBOOL_UNKNOWN) + { + uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))]; + struct iovec iov; + + iov.iov_base = xstateregs; + iov.iov_len = sizeof (xstateregs); + + /* Check if PTRACE_GETREGSET works. */ + if (ptrace (PTRACE_GETREGSET, tid, + (unsigned int) NT_X86_XSTATE, &iov) < 0) + have_ptrace_getregset = TRIBOOL_FALSE; + else + { + have_ptrace_getregset = TRIBOOL_TRUE; + + /* Get XCR0 from XSAVE extended state. */ + xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET + / sizeof (uint64_t))]; + + m_xsave_layout = x86_fetch_xsave_layout (xcr0, x86_xsave_length ()); + } + } + + /* Check the native XCR0 only if PTRACE_GETREGSET is available. If + PTRACE_GETREGSET is not available then set xcr0_features_bits to + zero so that the "no-features" descriptions are returned by the + switches below. */ + if (have_ptrace_getregset == TRIBOOL_TRUE) + xcr0_features_bits = xcr0 & X86_XSTATE_ALL_MASK; + else + xcr0_features_bits = 0; + + if (is_64bit) + { +#ifdef __x86_64__ + return amd64_linux_read_description (xcr0_features_bits, is_x32); +#endif + } + else + { + const struct target_desc * tdesc + = i386_linux_read_description (xcr0_features_bits); - const char *error_msg - = _("Can't debug 64-bit process with 32-bit GDB"); + if (tdesc == NULL) + tdesc = i386_linux_read_description (X86_XSTATE_SSE_MASK); - /* Callback that is triggered the first time x86_linux_tdesc_for_tid - reads the xcr0 register. Setup other bits of state */ - auto cb = [&] (uint64_t xcr0) - { - this->m_xsave_layout - = x86_fetch_xsave_layout (xcr0, x86_xsave_length ()); - }; + return tdesc; + } - return x86_linux_tdesc_for_tid (tid, &have_ptrace_getregset, cb, - error_msg, &xcr0_storage); + gdb_assert_not_reached ("failed to return tdesc"); } |