aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2024-03-26 18:52:44 +0000
committerAndrew Burgess <aburgess@redhat.com>2024-03-26 18:52:44 +0000
commit49a7660fb50cc3c68e7830eb098905d068a3ccbf (patch)
tree8471a0dcc41846551322f58510aa9aea098356c5
parent0991b56074af7e6b106015c67925fdcfe039f077 (diff)
downloadbinutils-49a7660fb50cc3c68e7830eb098905d068a3ccbf.zip
binutils-49a7660fb50cc3c68e7830eb098905d068a3ccbf.tar.gz
binutils-49a7660fb50cc3c68e7830eb098905d068a3ccbf.tar.bz2
Revert "gdb/gdbserver: share some code relating to target description creation"
This reverts commit cd9b374ffe372dcaf7e4c15548cf53a301d8dcdd.
-rw-r--r--gdb/Makefile.in1
-rw-r--r--gdb/amd64-linux-tdep.c1
-rw-r--r--gdb/amd64-linux-tdep.h6
-rw-r--r--gdb/configure.nat4
-rw-r--r--gdb/i386-linux-tdep.c1
-rw-r--r--gdb/i386-linux-tdep.h3
-rw-r--r--gdb/nat/x86-linux-tdesc.c124
-rw-r--r--gdb/nat/x86-linux-tdesc.h75
-rw-r--r--gdb/x86-linux-nat.c91
-rw-r--r--gdbserver/configure.srv2
-rw-r--r--gdbserver/linux-amd64-ipa.cc1
-rw-r--r--gdbserver/linux-i386-ipa.cc1
-rw-r--r--gdbserver/linux-x86-low.cc148
-rw-r--r--gdbserver/linux-x86-tdesc.cc1
-rw-r--r--gdbserver/linux-x86-tdesc.h7
15 files changed, 199 insertions, 267 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 38f4d5f..3316203 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1585,7 +1585,6 @@ HFILES_NO_SRCDIR = \
nat/x86-gcc-cpuid.h \
nat/x86-linux.h \
nat/x86-linux-dregs.h \
- nat/x86-linux-tdesc.h \
python/py-event.h \
python/py-events.h \
python/py-stopevent.h \
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index 7e0900d..a512ec5 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -43,7 +43,6 @@
#include "target-descriptions.h"
#include "expop.h"
#include "nat/x86-linux.h"
-#include "nat/x86-linux-tdesc.h"
/* The syscall's XML filename for i386. */
#define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml"
diff --git a/gdb/amd64-linux-tdep.h b/gdb/amd64-linux-tdep.h
index 0ec49e7..2003dcd 100644
--- a/gdb/amd64-linux-tdep.h
+++ b/gdb/amd64-linux-tdep.h
@@ -43,6 +43,12 @@ extern struct target_desc *tdesc_x32_linux;
extern struct target_desc *tdesc_x32_avx_linux;
extern struct target_desc *tdesc_x32_avx_avx512_linux;
+/* Return the right amd64-linux target descriptions according to
+ XCR0_FEATURES_BIT and IS_X32. */
+
+const target_desc *amd64_linux_read_description (uint64_t xcr0_features_bit,
+ bool is_x32);
+
/* Enum that defines the syscall identifiers for amd64 linux.
Used for process record/replay, these will be translated into
a gdb-canonical set of syscall ids in linux-record.c. */
diff --git a/gdb/configure.nat b/gdb/configure.nat
index 4bcc069..8b98511 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -256,7 +256,7 @@ case ${gdb_host} in
NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
nat/x86-xstate.o \
i386-linux-nat.o x86-linux-nat.o nat/linux-btrace.o \
- nat/x86-linux.o nat/x86-linux-dregs.o nat/x86-linux-tdesc.o"
+ nat/x86-linux.o nat/x86-linux-dregs.o"
;;
ia64)
# Host: Intel IA-64 running GNU/Linux
@@ -322,7 +322,7 @@ case ${gdb_host} in
NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
nat/x86-xstate.o amd64-nat.o amd64-linux-nat.o x86-linux-nat.o \
nat/linux-btrace.o \
- nat/x86-linux.o nat/x86-linux-dregs.o nat/x86-linux-tdesc.o \
+ nat/x86-linux.o nat/x86-linux-dregs.o \
nat/amd64-linux-siginfo.o"
;;
sparc)
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index f5f7a36..8dd7203 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -41,7 +41,6 @@
#include "i387-tdep.h"
#include "gdbsupport/x86-xstate.h"
#include "nat/x86-linux.h"
-#include "nat/x86-linux-tdesc.h"
/* The syscall's XML filename for i386. */
#define XML_SYSCALL_FILENAME_I386 "syscalls/i386-linux.xml"
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index e8691cd..07593c6 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -55,6 +55,9 @@ extern void i386_linux_report_signal_info (struct gdbarch *gdbarch,
struct ui_out *uiout,
enum gdb_signal siggnal);
+/* Return the target description according to XCR0. */
+extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
+
extern int i386_linux_gregset_reg_offset[];
/* Return x86 siginfo type. */
diff --git a/gdb/nat/x86-linux-tdesc.c b/gdb/nat/x86-linux-tdesc.c
deleted file mode 100644
index be7014d..0000000
--- a/gdb/nat/x86-linux-tdesc.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* Target description related code for GNU/Linux x86 (i386 and x86-64).
-
- Copyright (C) 2024 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "gdbsupport/common-defs.h"
-#include "nat/x86-linux-tdesc.h"
-#ifdef __x86_64__
-#include "arch/amd64.h"
-#endif
-#include "arch/i386.h"
-
-#include "gdbsupport/common-defs.h"
-#include "nat/x86-linux.h"
-#include "nat/x86-linux-dregs.h"
-#include "nat/gdb_ptrace.h"
-#include "nat/x86-xstate.h"
-#include "nat/x86-linux-tdesc.h"
-
-#include <cstdint>
-#include <cstdlib>
-#include <linux/uio.h>
-#include <elf.h>
-#include <sys/user.h>
-#include <sys/user.h>
-
-/* See nat/x86-linux-tdesc.h. */
-
-const target_desc *
-x86_linux_tdesc_for_tid (int tid, enum tribool *have_ptrace_getregset,
- gdb::function_view<void (uint64_t)> xcr0_init_cb,
- const char *error_msg, uint64_t *xcr0_storage)
-{
-#ifdef __x86_64__
-
- x86_linux_arch_size arch_size = x86_linux_ptrace_get_arch_size (tid);
- bool is_64bit = arch_size.is_64bit ();
- bool is_x32 = arch_size.is_x32 ();
-
- if (sizeof (void *) == 4 && is_64bit && !is_x32)
- error ("%s", error_msg);
-
-#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;
- *xcr0_storage = 0;
- }
- else
- {
- *have_ptrace_getregset = TRIBOOL_TRUE;
-
- /* Get XCR0 from XSAVE extended state. */
- *xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
- / sizeof (uint64_t))];
-
-#ifdef __x86_64__
- /* No MPX on x32. */
- if (is_64bit && is_x32)
- *xcr0_storage &= ~X86_XSTATE_MPX;
-#endif /* __x86_64__ */
-
- xcr0_init_cb (*xcr0_storage);
- }
- }
-
- /* 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. */
- uint64_t xcr0_features_bits;
- if (*have_ptrace_getregset == TRIBOOL_TRUE)
- xcr0_features_bits = *xcr0_storage & X86_XSTATE_ALL_MASK;
- else
- xcr0_features_bits = 0;
-
-#ifdef __x86_64__
- if (is_64bit)
- {
- return amd64_linux_read_description (xcr0_features_bits, is_x32);
- }
- else
-#endif
- return i386_linux_read_description (xcr0_features_bits);
-
- gdb_assert_not_reached ("failed to return tdesc");
-}
diff --git a/gdb/nat/x86-linux-tdesc.h b/gdb/nat/x86-linux-tdesc.h
deleted file mode 100644
index 3727a8b..0000000
--- a/gdb/nat/x86-linux-tdesc.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Target description related code for GNU/Linux x86 (i386 and x86-64).
-
- Copyright (C) 2024 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef NAT_X86_LINUX_TDESC_H
-#define NAT_X86_LINUX_TDESC_H
-
-#include "gdbsupport/function-view.h"
-
-struct target_desc;
-
-/* Return the target description for Linux thread TID.
-
- When *HAVE_PTRACE_GETREGSET is TRIBOOL_UNKNOWN then the current value of
- xcr0 is read using ptrace calls and stored into *XCR0_STORAGE. Then
- XCR0_INIT_CB is called with the value of *XCR0_STORAGE and
- *HAVE_PTRACE_GETREGSET is set to TRIBOOL_TRUE.
-
- If the attempt to read xcr0 using ptrace fails then *XCR0_STORAGE is set
- to zero and *HAVE_PTRACE_GETREGSET is set to TRIBOOL_FALSE.
-
- The storage pointed to by XCR0_STORAGE must exist until the program
- terminates, this storage is used to cache the xcr0 value. As such
- XCR0_INIT_CB will only be called once if xcr0 is successfully read using
- ptrace, or not at all if the ptrace call fails.
-
- This function returns a target description based on the extracted xcr0
- value along with other characteristics of the thread identified by TID.
-
- This function can return nullptr if we encounter a machine configuration
- for which a target_desc cannot be created. Ideally this would not be
- the case, we should be able to create a target description for every
- possible machine configuration. See amd64_linux_read_description and
- i386_linux_read_description for cases when nullptr might be
- returned.
-
- ERROR_MSG is using in an error() call if we try to create a target
- description for a 64-bit process but this is a 32-bit build of GDB. */
-
-extern const target_desc *
-x86_linux_tdesc_for_tid (int tid, enum tribool *have_ptrace_getregset,
- gdb::function_view<void (uint64_t)> xcr0_init_cb,
- const char *error_msg, uint64_t *xcr0_storage);
-
-#ifdef __x86_64__
-
-/* Return the right amd64-linux target descriptions according to
- XCR0_FEATURES_BIT and IS_X32. This is implemented separately in both
- GDB and gdbserver. */
-
-extern const target_desc *amd64_linux_read_description
- (uint64_t xcr0_features_bit, bool is_x32);
-
-#endif
-
-/* Return the target description according to XCR0. This is implemented
- separately in both GDB and gdbserver. */
-extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
-
-#endif /* NAT_X86_LINUX_TDESC_H */
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");
}
diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv
index 7a2702d..9e861a7 100644
--- a/gdbserver/configure.srv
+++ b/gdbserver/configure.srv
@@ -109,7 +109,6 @@ case "${gdbserver_host}" in
srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
srv_tgtobj="${srv_tgtobj} nat/x86-linux.o"
srv_tgtobj="${srv_tgtobj} nat/x86-linux-dregs.o"
- srv_tgtobj="${srv_tgtobj} nat/x86-linux-tdesc.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -372,7 +371,6 @@ case "${gdbserver_host}" in
srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
srv_tgtobj="${srv_tgtobj} nat/x86-linux.o"
srv_tgtobj="${srv_tgtobj} nat/x86-linux-dregs.o"
- srv_tgtobj="${srv_tgtobj} nat/x86-linux-tdesc.o"
srv_tgtobj="${srv_tgtobj} nat/amd64-linux-siginfo.o"
srv_linux_usrregs=yes # This is for i386 progs.
srv_linux_regsets=yes
diff --git a/gdbserver/linux-amd64-ipa.cc b/gdbserver/linux-amd64-ipa.cc
index f97b0d6..54e4c98 100644
--- a/gdbserver/linux-amd64-ipa.cc
+++ b/gdbserver/linux-amd64-ipa.cc
@@ -23,7 +23,6 @@
#include "tracepoint.h"
#include "linux-x86-tdesc.h"
#include "gdbsupport/x86-xstate.h"
-#include "nat/x86-linux-tdesc.h"
/* Defined in auto-generated file amd64-linux.c. */
void init_registers_amd64_linux (void);
diff --git a/gdbserver/linux-i386-ipa.cc b/gdbserver/linux-i386-ipa.cc
index 459b805..2e4646f 100644
--- a/gdbserver/linux-i386-ipa.cc
+++ b/gdbserver/linux-i386-ipa.cc
@@ -23,7 +23,6 @@
#include "tracepoint.h"
#include "linux-x86-tdesc.h"
#include "gdbsupport/x86-xstate.h"
-#include "nat/x86-linux-tdesc.h"
/* GDB register numbers. */
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
index 9bf369f..30d876e 100644
--- a/gdbserver/linux-x86-low.cc
+++ b/gdbserver/linux-x86-low.cc
@@ -48,7 +48,6 @@
#include "nat/x86-linux.h"
#include "nat/x86-linux-dregs.h"
#include "linux-x86-tdesc.h"
-#include "nat/x86-linux-tdesc.h"
#ifdef __x86_64__
static target_desc_up tdesc_amd64_linux_no_xml;
@@ -845,20 +844,32 @@ int have_ptrace_getfpxregs =
#endif
;
-/* Cached xcr0 value. This is initialised the first time
- x86_linux_read_description is called. */
-
-static uint64_t xcr0_storage;
-
/* Get Linux/x86 target description from running target. */
static const struct target_desc *
x86_linux_read_description (void)
{
- int tid = lwpid_of (current_thread);
+ unsigned int machine;
+ int is_elf64;
+ int xcr0_features;
+ int tid;
+ static uint64_t xcr0;
+ static int xsave_len;
+ struct regset_info *regset;
+
+ tid = lwpid_of (current_thread);
+
+ is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
- const char *error_msg
- = _("Can't debug 64-bit process with 32-bit GDBserver");
+ if (sizeof (void *) == 4)
+ {
+ if (is_elf64 > 0)
+ error (_("Can't debug 64-bit process with 32-bit GDBserver"));
+#ifndef __x86_64__
+ else if (machine == EM_X86_64)
+ error (_("Can't debug x86-64 process with 32-bit GDBserver"));
+#endif
+ }
/* If we are not allowed to send an XML target description then we need
to use the hard-wired target descriptions. This corresponds to GDB's
@@ -868,54 +879,103 @@ x86_linux_read_description (void)
generate some alternative target descriptions. */
if (!use_xml)
{
- x86_linux_arch_size arch_size = x86_linux_ptrace_get_arch_size (tid);
- bool is_64bit = arch_size.is_64bit ();
- bool is_x32 = arch_size.is_x32 ();
-
- if (sizeof (void *) == 4 && is_64bit && !is_x32)
- error ("%s", error_msg);
-
#ifdef __x86_64__
- if (is_64bit && !is_x32)
+ if (machine == EM_X86_64)
return tdesc_amd64_linux_no_xml.get ();
else
#endif
return tdesc_i386_linux_no_xml.get ();
}
- /* 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)
- {
- i387_set_xsave_mask (xcr0, x86_xsave_length ());
- };
+#if !defined __x86_64__ && defined HAVE_PTRACE_GETFPXREGS
+ if (machine == EM_386 && have_ptrace_getfpxregs == -1)
+ {
+ elf_fpxregset_t fpxregs;
- /* If have_ptrace_getregset is changed to true by calling
- x86_linux_tdesc_for_tid then we will perform some additional
- initialisation. */
- bool have_ptrace_getregset_is_unknown
- = have_ptrace_getregset == TRIBOOL_UNKNOWN;
+ if (ptrace (PTRACE_GETFPXREGS, tid, 0, (long) &fpxregs) < 0)
+ {
+ have_ptrace_getfpxregs = 0;
+ have_ptrace_getregset = TRIBOOL_FALSE;
+ return i386_linux_read_description (X86_XSTATE_X87);
+ }
+ else
+ have_ptrace_getfpxregs = 1;
+ }
+#endif
- const target_desc *tdesc
- = x86_linux_tdesc_for_tid (tid, &have_ptrace_getregset, cb, error_msg,
- &xcr0_storage);
+ if (have_ptrace_getregset == TRIBOOL_UNKNOWN)
+ {
+ uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))];
+ struct iovec iov;
- if (have_ptrace_getregset_is_unknown
- && have_ptrace_getregset == TRIBOOL_TRUE)
+ iov.iov_base = xstateregs;
+ iov.iov_len = sizeof (xstateregs);
+
+ /* Check if PTRACE_GETREGSET works. */
+ if (ptrace (PTRACE_GETREGSET, tid,
+ (unsigned int) NT_X86_XSTATE, (long) &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))];
+
+ /* No MPX on x32. */
+ if (machine == EM_X86_64 && !is_elf64)
+ xcr0 &= ~X86_XSTATE_MPX;
+
+ xsave_len = x86_xsave_length ();
+
+ /* Use PTRACE_GETREGSET if it is available. */
+ for (regset = x86_regsets;
+ regset->fill_function != NULL; regset++)
+ if (regset->get_request == PTRACE_GETREGSET)
+ regset->size = xsave_len;
+ else if (regset->type != GENERAL_REGS)
+ regset->size = 0;
+ }
+ }
+
+ /* Check the native XCR0 only if PTRACE_GETREGSET is available. */
+ xcr0_features = (have_ptrace_getregset == TRIBOOL_TRUE
+ && (xcr0 & X86_XSTATE_ALL_MASK));
+
+ if (xcr0_features)
+ i387_set_xsave_mask (xcr0, xsave_len);
+
+ if (machine == EM_X86_64)
+ {
+#ifdef __x86_64__
+ const target_desc *tdesc = NULL;
+
+ if (xcr0_features)
+ {
+ tdesc = amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
+ !is_elf64);
+ }
+
+ if (tdesc == NULL)
+ tdesc = amd64_linux_read_description (X86_XSTATE_SSE_MASK, !is_elf64);
+ return tdesc;
+#endif
+ }
+ else
{
- int xsave_len = x86_xsave_length ();
-
- /* Use PTRACE_GETREGSET if it is available. */
- for (regset_info *regset = x86_regsets;
- regset->fill_function != nullptr;
- regset++)
- if (regset->get_request == PTRACE_GETREGSET)
- regset->size = xsave_len;
- else if (regset->type != GENERAL_REGS)
- regset->size = 0;
+ const target_desc *tdesc = NULL;
+
+ if (xcr0_features)
+ tdesc = i386_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK);
+
+ if (tdesc == NULL)
+ tdesc = i386_linux_read_description (X86_XSTATE_SSE);
+
+ return tdesc;
}
- return tdesc;
+ gdb_assert_not_reached ("failed to return tdesc");
}
/* Update all the target description of all processes; a new GDB
diff --git a/gdbserver/linux-x86-tdesc.cc b/gdbserver/linux-x86-tdesc.cc
index 9fd64d8..626207f 100644
--- a/gdbserver/linux-x86-tdesc.cc
+++ b/gdbserver/linux-x86-tdesc.cc
@@ -26,7 +26,6 @@
#include "arch/amd64.h"
#endif
#include "x86-tdesc.h"
-#include "nat/x86-linux-tdesc.h"
/* Return the right x86_linux_tdesc index for a given XCR0. Return
X86_TDESC_LAST if can't find a match. */
diff --git a/gdbserver/linux-x86-tdesc.h b/gdbserver/linux-x86-tdesc.h
index 576aaf5..f9561b1 100644
--- a/gdbserver/linux-x86-tdesc.h
+++ b/gdbserver/linux-x86-tdesc.h
@@ -46,4 +46,11 @@ int amd64_get_ipa_tdesc_idx (const struct target_desc *tdesc);
const struct target_desc *i386_get_ipa_tdesc (int idx);
+#ifdef __x86_64__
+const struct target_desc *amd64_linux_read_description (uint64_t xcr0,
+ bool is_x32);
+#endif
+
+const struct target_desc *i386_linux_read_description (uint64_t xcr0);
+
#endif /* GDBSERVER_LINUX_X86_TDESC_H */