- bfd_target_elf_flavour, /* core_flavour */
- default_check_format, /* check_format */
- default_core_sniffer, /* core_sniffer */
- fetch_core_registers, /* core_read_registers */
- NULL /* next */
-};
+ int tid;
+ static uint64_t xcr0;
+
+ /* GNU/Linux LWP ID's are process ID's. */
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+
+#ifdef 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 = 0;
+ return tdesc_i386_mmx_linux;
+ }
+ }
+#endif
+
+ if (have_ptrace_getregset == -1)
+ {
+ uint64_t xstateregs[(I386_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 = 0;
+ else
+ {
+ have_ptrace_getregset = 1;
+
+ /* Get XCR0 from XSAVE extended state. */
+ xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
+ / sizeof (long long))];
+ }
+ }
+
+ /* Check the native XCR0 only if PTRACE_GETREGSET is available. */
+ if (have_ptrace_getregset
+ && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK)
+ return tdesc_i386_avx_linux;
+ else
+ return tdesc_i386_linux;
+}