gdb: Support XSAVE layouts for the current host in the Linux x86 targets.
authorJohn Baldwin <jhb@FreeBSD.org>
Mon, 28 Aug 2023 21:18:19 +0000 (14:18 -0700)
committerJohn Baldwin <jhb@FreeBSD.org>
Mon, 28 Aug 2023 21:18:19 +0000 (14:18 -0700)
Note that this uses the CPUID instruction to determine the total size
of the XSAVE register set.  If there is a way to fetch the register set
size using ptrace that would probably be better.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/amd64-linux-nat.c
gdb/configure.nat
gdb/i386-linux-nat.c
gdb/x86-linux-nat.c
gdb/x86-linux-nat.h

index b5b0703879b994189169757b861d7e4cc756c60e..6571be40bb5e14dbfc6ed4b75ce00bcd7f08770c 100644 (file)
@@ -210,6 +210,7 @@ void
 amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
 {
   struct gdbarch *gdbarch = regcache->arch ();
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int tid;
 
   /* GNU/Linux LWP ID's are process ID's.  */
@@ -235,7 +236,7 @@ amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
 
       if (have_ptrace_getregset == TRIBOOL_TRUE)
        {
-         char xstateregs[X86_XSTATE_MAX_SIZE];
+         char xstateregs[tdep->xsave_layout.sizeof_xsave];
          struct iovec iov;
 
          /* Pre-4.14 kernels have a bug (fixed by commit 0852b374173b
@@ -270,6 +271,7 @@ void
 amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
 {
   struct gdbarch *gdbarch = regcache->arch ();
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int tid;
 
   /* GNU/Linux LWP ID's are process ID's.  */
@@ -299,7 +301,7 @@ amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
 
       if (have_ptrace_getregset == TRIBOOL_TRUE)
        {
-         char xstateregs[X86_XSTATE_MAX_SIZE];
+         char xstateregs[tdep->xsave_layout.sizeof_xsave];
          struct iovec iov;
 
          iov.iov_base = xstateregs;
index b371ad89afe816ba2f880f6359c730e67d4e2e3e..2739d14a1c4e79fe68d593a1e4d4adf25316ac73 100644 (file)
@@ -254,6 +254,7 @@ case ${gdb_host} in
            i386)
                # Host: Intel 386 running GNU/Linux.
                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"
                ;;
@@ -319,7 +320,7 @@ case ${gdb_host} in
            i386)
                # Host: GNU/Linux x86-64
                NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
-               amd64-nat.o amd64-linux-nat.o x86-linux-nat.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/amd64-linux-siginfo.o"
index a524fdc9a1da78c810f97471a1452c064d3bc7c8..7e0572e19070250ef7b0db95e0ef64b022844ac8 100644 (file)
@@ -330,7 +330,9 @@ store_fpregs (const struct regcache *regcache, int tid, int regno)
 static int
 fetch_xstateregs (struct regcache *regcache, int tid)
 {
-  char xstateregs[X86_XSTATE_MAX_SIZE];
+  struct gdbarch *gdbarch = regcache->arch ();
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+  char xstateregs[tdep->xsave_layout.sizeof_xsave];
   struct iovec iov;
 
   if (have_ptrace_getregset != TRIBOOL_TRUE)
@@ -353,7 +355,9 @@ fetch_xstateregs (struct regcache *regcache, int tid)
 static int
 store_xstateregs (const struct regcache *regcache, int tid, int regno)
 {
-  char xstateregs[X86_XSTATE_MAX_SIZE];
+  struct gdbarch *gdbarch = regcache->arch ();
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+  char xstateregs[tdep->xsave_layout.sizeof_xsave];
   struct iovec iov;
 
   if (have_ptrace_getregset != TRIBOOL_TRUE)
index ca4eaf5b645146fc7d140923c0e382c0dfe4b75a..cd8fd9c1dcdeccce76ef91341b9dc2d97b69079b 100644 (file)
@@ -36,6 +36,7 @@
 #include "amd64-linux-tdep.h"
 #endif
 #include "gdbsupport/x86-xstate.h"
+#include "nat/x86-xstate.h"
 #include "nat/linux-btrace.h"
 #include "nat/linux-nat.h"
 #include "nat/x86-linux.h"
@@ -179,6 +180,8 @@ x86_linux_nat_target::read_description ()
          /* 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 ());
        }
     }
 
index fcb5f08d25157eac206f8bde879877f8a1fb86e9..a99de6c29ea04da64e0fe880c84143fa69bc96c9 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "gdb_proc_service.h"  /* For ps_err_e.  */
 #include "linux-nat.h"
+#include "gdbsupport/x86-xstate.h"
 #include "x86-nat.h"
 #include "nat/x86-linux.h"
 
@@ -41,6 +42,9 @@ struct x86_linux_nat_target : public x86_nat_target<linux_nat_target>
                                 enum btrace_read_type type) override;
   const struct btrace_config *btrace_conf (const struct btrace_target_info *) override;
 
+  x86_xsave_layout fetch_x86_xsave_layout () override
+  { return m_xsave_layout; }
+
   /* These two are rewired to low_ versions.  linux-nat.c queries
      stopped-by-watchpoint info as soon as an lwp stops (via the low_
      methods) and caches the result, to be returned via the normal
@@ -74,6 +78,9 @@ struct x86_linux_nat_target : public x86_nat_target<linux_nat_target>
 protected:
   /* Override the GNU/Linux inferior startup hook.  */
   void post_startup_inferior (ptid_t) override;
+
+private:
+  x86_xsave_layout m_xsave_layout;
 };
 
 \f