public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v6 00/15] Handle variable XSAVE layouts
@ 2023-07-14 15:51 John Baldwin
  2023-07-14 15:51 ` [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle " John Baldwin
                   ` (16 more replies)
  0 siblings, 17 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

Changes since V5:

- A few fixes not tied to the new layout handling have been merged to
  master.

- Reworded the comment describing i386_*_core_read_xsave_info in patches
  6 and 8.

Aleksandar Paunovic (2):
  gdbserver: Refactor the legacy region within the xsave struct
  gdbserver: Use x86_xstate_layout to parse the XSAVE extended state
    area.

John Baldwin (13):
  x86: Add an x86_xsave_layout structure to handle variable XSAVE
    layouts.
  gdb: Store an x86_xsave_layout in i386_gdbarch_tdep.
  core: Support fetching x86 XSAVE layout from architectures.
  nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count.
  x86 nat: Add helper functions to save the XSAVE layout for the host.
  gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
  gdb: Support XSAVE layouts for the current host in the FreeBSD x86
    targets.
  gdb: Update x86 Linux architectures to support XSAVE layouts.
  gdb: Support XSAVE layouts for the current host in the Linux x86
    targets.
  gdb: Use x86_xstate_layout to parse the XSAVE extended state area.
  gdbserver: Add a function to set the XSAVE mask and size.
  x86: Remove X86_XSTATE_SIZE and related constants.
  gdbserver: Simplify handling of ZMM registers.

 gdb/amd64-fbsd-nat.c       |  40 +--
 gdb/amd64-fbsd-tdep.c      |  12 +-
 gdb/amd64-linux-nat.c      |   6 +-
 gdb/amd64-linux-tdep.c     |  11 +-
 gdb/configure.nat          |   8 +-
 gdb/corelow.c              |  21 ++
 gdb/gdbarch-gen.h          |   9 +
 gdb/gdbarch.c              |  32 +++
 gdb/gdbarch.h              |   1 +
 gdb/gdbarch_components.py  |  11 +
 gdb/i386-fbsd-nat.c        |  39 +--
 gdb/i386-fbsd-tdep.c       |  72 ++---
 gdb/i386-fbsd-tdep.h       |  14 +-
 gdb/i386-linux-nat.c       |   8 +-
 gdb/i386-linux-tdep.c      |  67 ++---
 gdb/i386-linux-tdep.h      |  25 +-
 gdb/i386-tdep.c            |  18 +-
 gdb/i386-tdep.h            |   4 +
 gdb/i387-tdep.c            | 522 +++++++++++++++++++++++--------------
 gdb/i387-tdep.h            |   9 +
 gdb/nat/x86-cpuid.h        |  32 +++
 gdb/nat/x86-xstate.c       |  67 +++++
 gdb/nat/x86-xstate.h       |  35 +++
 gdb/target-debug.h         |  20 ++
 gdb/target-delegates.c     |  27 ++
 gdb/target.c               |   6 +
 gdb/target.h               |   7 +
 gdb/x86-fbsd-nat.c         |  21 ++
 gdb/x86-fbsd-nat.h         |  19 ++
 gdb/x86-linux-nat.c        |   3 +
 gdb/x86-linux-nat.h        |   7 +
 gdbserver/configure.srv    |  12 +-
 gdbserver/i387-fp.cc       | 268 +++++++++----------
 gdbserver/i387-fp.h        |   4 +-
 gdbserver/linux-x86-low.cc |  10 +-
 gdbsupport/x86-xstate.h    |  77 ++++--
 36 files changed, 1027 insertions(+), 517 deletions(-)
 create mode 100644 gdb/nat/x86-xstate.c
 create mode 100644 gdb/nat/x86-xstate.h

-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle variable XSAVE layouts.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 19:22   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 02/15] gdb: Store an x86_xsave_layout in i386_gdbarch_tdep John Baldwin
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Aleksandar Paunovic

The standard layout of the XSAVE extended state area consists of three
regions.  The first 512 bytes (legacy region) match the layout of the
FXSAVE instruction including floating point registers, MMX registers,
and SSE registers.  The next 64 bytes (XSAVE header) contains a header
with a fixed layout.  The final region (extended region) contains zero
or more optional state components.  Examples of these include the
upper 128 bits of YMM registers for AVX.

These optional state components generally have an
architecturally-fixed size, but they are not assigned architectural
offsets in the extended region.  Instead, processors provide
additional CPUID leafs describing the size and offset of each
component in the "standard" layout for a given CPU.  (There is also a
"compact" format which uses an alternate layout, but existing OS's
currently export the "standard" layout when exporting XSAVE data via
ptrace() and core dumps.)

To date, GDB has assumed the layout used on current Intel processors
for state components in the extended region and hardcoded those
offsets in the tables in i387-tdep.c and i387-fp.cc.  However, this
fails on recent AMD processors which use a different layout.
Specifically, AMD Zen3 and later processors do not leave space for the
MPX register set in between the AVX and AVX512 register sets.

To rectify this, add an x86_xsave_layout structure which contains the
total size of the XSAVE extended state area as well as the offset of
each known optional state component.

Subsequent commits will modify XSAVE parsing in both gdb and gdbserver
to use x86_xsave_layout.

Co-authored-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
---
 gdbsupport/x86-xstate.h | 65 +++++++++++++++++++++++++++++++++++------
 1 file changed, 56 insertions(+), 9 deletions(-)

diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
index b8740fd8701..27fc0bd12f2 100644
--- a/gdbsupport/x86-xstate.h
+++ b/gdbsupport/x86-xstate.h
@@ -20,22 +20,69 @@
 #ifndef COMMON_X86_XSTATE_H
 #define COMMON_X86_XSTATE_H
 
+/* The extended state feature IDs in the state component bitmap.  */
+#define X86_XSTATE_X87_ID	0
+#define X86_XSTATE_SSE_ID	1
+#define X86_XSTATE_AVX_ID	2
+#define X86_XSTATE_BNDREGS_ID	3
+#define X86_XSTATE_BNDCFG_ID	4
+#define X86_XSTATE_K_ID		5
+#define X86_XSTATE_ZMM_H_ID	6
+#define X86_XSTATE_ZMM_ID	7
+#define X86_XSTATE_PKRU_ID	9
+
 /* The extended state feature bits.  */
-#define X86_XSTATE_X87		(1ULL << 0)
-#define X86_XSTATE_SSE		(1ULL << 1)
-#define X86_XSTATE_AVX		(1ULL << 2)
-#define X86_XSTATE_BNDREGS	(1ULL << 3)
-#define X86_XSTATE_BNDCFG	(1ULL << 4)
+#define X86_XSTATE_X87		(1ULL << X86_XSTATE_X87_ID)
+#define X86_XSTATE_SSE		(1ULL << X86_XSTATE_SSE_ID)
+#define X86_XSTATE_AVX		(1ULL << X86_XSTATE_AVX_ID)
+#define X86_XSTATE_BNDREGS	(1ULL << X86_XSTATE_BNDREGS_ID)
+#define X86_XSTATE_BNDCFG	(1ULL << X86_XSTATE_BNDCFG_ID)
 #define X86_XSTATE_MPX		(X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG)
 
 /* AVX 512 adds three feature bits.  All three must be enabled.  */
-#define X86_XSTATE_K		(1ULL << 5)
-#define X86_XSTATE_ZMM_H	(1ULL << 6)
-#define X86_XSTATE_ZMM		(1ULL << 7)
+#define X86_XSTATE_K		(1ULL << X86_XSTATE_K_ID)
+#define X86_XSTATE_ZMM_H	(1ULL << X86_XSTATE_ZMM_H_ID)
+#define X86_XSTATE_ZMM		(1ULL << X86_XSTATE_ZMM_ID)
 #define X86_XSTATE_AVX512	(X86_XSTATE_K | X86_XSTATE_ZMM_H \
 				 | X86_XSTATE_ZMM)
 
-#define X86_XSTATE_PKRU		(1ULL << 9)
+#define X86_XSTATE_PKRU		(1ULL << X86_XSTATE_PKRU_ID)
+
+/* Size and offsets of register states in the XSAVE area extended
+   region.  Offsets are set to 0 to indicate the absence of the
+   associated registers.  */
+
+struct x86_xsave_layout
+{
+  int sizeof_xsave = 0;
+  int avx_offset = 0;
+  int bndregs_offset = 0;
+  int bndcfg_offset = 0;
+  int k_offset = 0;
+  int zmm_h_offset = 0;
+  int zmm_offset = 0;
+  int pkru_offset = 0;
+};
+
+constexpr bool operator== (const x86_xsave_layout &lhs,
+			   const x86_xsave_layout &rhs)
+{
+  return lhs.sizeof_xsave == rhs.sizeof_xsave
+    && lhs.avx_offset == rhs.avx_offset
+    && lhs.bndregs_offset == rhs.bndregs_offset
+    && lhs.bndcfg_offset == rhs.bndcfg_offset
+    && lhs.k_offset == rhs.k_offset
+    && lhs.zmm_h_offset == rhs.zmm_h_offset
+    && lhs.zmm_offset == rhs.zmm_offset
+    && lhs.pkru_offset == rhs.pkru_offset;
+}
+
+constexpr bool operator!= (const x86_xsave_layout &lhs,
+			   const x86_xsave_layout &rhs)
+{
+  return !(lhs == rhs);
+}
+
 
 /* Supported mask and size of the extended state.  */
 #define X86_XSTATE_X87_MASK	X86_XSTATE_X87
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 02/15] gdb: Store an x86_xsave_layout in i386_gdbarch_tdep.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
  2023-07-14 15:51 ` [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle " John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-14 15:51 ` [PATCH v6 03/15] core: Support fetching x86 XSAVE layout from architectures John Baldwin
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

This structure is fetched from the current target in i386_gdbarch_init
via a new "fetch_x86_xsave_layout" target method.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
---
 gdb/i386-tdep.c        | 18 +++++++++++++++---
 gdb/i386-tdep.h        |  4 ++++
 gdb/target-debug.h     | 20 ++++++++++++++++++++
 gdb/target-delegates.c | 27 +++++++++++++++++++++++++++
 gdb/target.c           |  6 ++++++
 gdb/target.h           |  7 +++++++
 6 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index a97e11647b9..d5423681802 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8504,10 +8504,21 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int bnd0_regnum;
   int num_bnd_cooked;
 
+  x86_xsave_layout xsave_layout = target_fetch_x86_xsave_layout ();
+
   /* If there is already a candidate, use it.  */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return arches->gdbarch;
+  for (arches = gdbarch_list_lookup_by_info (arches, &info);
+       arches != NULL;
+       arches = gdbarch_list_lookup_by_info (arches->next, &info))
+    {
+      /* Check that the XSAVE layout of ARCHES matches the layout for
+	 the current target.  */
+      i386_gdbarch_tdep *other_tdep
+	= gdbarch_tdep<i386_gdbarch_tdep> (arches->gdbarch);
+
+      if (other_tdep->xsave_layout == xsave_layout)
+	return arches->gdbarch;
+    }
 
   /* Allocate space for the new architecture.  Assume i386 for now.  */
   gdbarch *gdbarch
@@ -8762,6 +8773,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       gdbarch_free (gdbarch);
       return NULL;
     }
+  tdep->xsave_layout = xsave_layout;
 
   num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);
 
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index bf52020ab67..34dc53db8d9 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -23,6 +23,7 @@
 #include "gdbarch.h"
 #include "infrun.h"
 #include "expression.h"
+#include "gdbsupport/x86-xstate.h"
 
 class frame_info_ptr;
 struct gdbarch;
@@ -145,6 +146,9 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
   /* Offset of XCR0 in XSAVE extended state.  */
   int xsave_xcr0_offset = 0;
 
+  /* Layout of the XSAVE area extended region.  */
+  x86_xsave_layout xsave_layout;
+
   /* Register names.  */
   const char * const *register_names = nullptr;
 
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
index acb01d47e7c..6b8983104ea 100644
--- a/gdb/target-debug.h
+++ b/gdb/target-debug.h
@@ -236,4 +236,24 @@ target_debug_print_gdb_byte_vector_r (gdb::byte_vector &vector)
 {
   target_debug_print_const_gdb_byte_vector_r (vector);
 }
+
+static void
+target_debug_print_x86_xsave_layout (const x86_xsave_layout &layout)
+{
+  gdb_puts ("{", gdb_stdlog);
+  gdb_printf (gdb_stdlog, " sizeof_xsave=%d", layout.sizeof_xsave);
+#define POFFS(region)							\
+  if (layout.region##_offset != 0)					\
+    gdb_printf (gdb_stdlog, ", %s_offset=%d", #region,			\
+		layout.region##_offset)
+  POFFS(avx);
+  POFFS(bndregs);
+  POFFS(bndcfg);
+  POFFS(k);
+  POFFS(zmm_h);
+  POFFS(zmm);
+  POFFS(pkru);
+#undef POFFS
+  gdb_puts (" }", gdb_stdlog);
+}
 #endif /* TARGET_DEBUG_H */
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 57b66ce87b1..1d1f8c60f4e 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -196,6 +196,7 @@ struct dummy_target : public target_ops
   bool supports_memory_tagging () override;
   bool fetch_memtags (CORE_ADDR arg0, size_t arg1, gdb::byte_vector &arg2, int arg3) override;
   bool store_memtags (CORE_ADDR arg0, size_t arg1, const gdb::byte_vector &arg2, int arg3) override;
+  x86_xsave_layout fetch_x86_xsave_layout () override;
 };
 
 struct debug_target : public target_ops
@@ -370,6 +371,7 @@ struct debug_target : public target_ops
   bool supports_memory_tagging () override;
   bool fetch_memtags (CORE_ADDR arg0, size_t arg1, gdb::byte_vector &arg2, int arg3) override;
   bool store_memtags (CORE_ADDR arg0, size_t arg1, const gdb::byte_vector &arg2, int arg3) override;
+  x86_xsave_layout fetch_x86_xsave_layout () override;
 };
 
 void
@@ -4536,3 +4538,28 @@ debug_target::store_memtags (CORE_ADDR arg0, size_t arg1, const gdb::byte_vector
   return result;
 }
 
+x86_xsave_layout
+target_ops::fetch_x86_xsave_layout ()
+{
+  return this->beneath ()->fetch_x86_xsave_layout ();
+}
+
+x86_xsave_layout
+dummy_target::fetch_x86_xsave_layout ()
+{
+  return x86_xsave_layout ();
+}
+
+x86_xsave_layout
+debug_target::fetch_x86_xsave_layout ()
+{
+  x86_xsave_layout result;
+  gdb_printf (gdb_stdlog, "-> %s->fetch_x86_xsave_layout (...)\n", this->beneath ()->shortname ());
+  result = this->beneath ()->fetch_x86_xsave_layout ();
+  gdb_printf (gdb_stdlog, "<- %s->fetch_x86_xsave_layout (", this->beneath ()->shortname ());
+  gdb_puts (") = ", gdb_stdlog);
+  target_debug_print_x86_xsave_layout (result);
+  gdb_puts ("\n", gdb_stdlog);
+  return result;
+}
+
diff --git a/gdb/target.c b/gdb/target.c
index 16f43d072cd..f650e5ccb51 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -832,6 +832,12 @@ target_store_memtags (CORE_ADDR address, size_t len,
   return current_inferior ()->top_target ()->store_memtags (address, len, tags, type);
 }
 
+x86_xsave_layout
+target_fetch_x86_xsave_layout ()
+{
+  return current_inferior ()->top_target ()->fetch_x86_xsave_layout ();
+}
+
 void
 target_log_command (const char *p)
 {
diff --git a/gdb/target.h b/gdb/target.h
index 6ae400e2cc2..9325b111c5b 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -82,6 +82,7 @@ struct inferior;
 #include "disasm-flags.h"
 #include "tracepoint.h"
 #include "gdbsupport/fileio.h"
+#include "gdbsupport/x86-xstate.h"
 
 #include "gdbsupport/break-common.h" /* For enum target_hw_bp_type.  */
 
@@ -1321,6 +1322,10 @@ struct target_ops
     virtual bool store_memtags (CORE_ADDR address, size_t len,
 				const gdb::byte_vector &tags, int type)
       TARGET_DEFAULT_NORETURN (tcomplain ());
+
+    /* Return the x86 XSAVE extended state area layout.  */
+    virtual x86_xsave_layout fetch_x86_xsave_layout ()
+      TARGET_DEFAULT_RETURN (x86_xsave_layout ());
   };
 
 /* Deleter for std::unique_ptr.  See comments in
@@ -2301,6 +2306,8 @@ extern bool target_fetch_memtags (CORE_ADDR address, size_t len,
 extern bool target_store_memtags (CORE_ADDR address, size_t len,
 				  const gdb::byte_vector &tags, int type);
 
+extern x86_xsave_layout target_fetch_x86_xsave_layout ();
+
 /* Command logging facility.  */
 
 extern void target_log_command (const char *p);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 03/15] core: Support fetching x86 XSAVE layout from architectures.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
  2023-07-14 15:51 ` [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle " John Baldwin
  2023-07-14 15:51 ` [PATCH v6 02/15] gdb: Store an x86_xsave_layout in i386_gdbarch_tdep John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 19:37   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 04/15] nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count John Baldwin
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

Add gdbarch_core_read_x86_xsave_layout to fetch the x86 XSAVE layout
structure from a core file.

Current OS's do not export the offsets of XSAVE state components in
core dumps, so provide an i387_set_xsave_layout helper function to set
offsets based on known combinations of XCR0 masks and total state
sizes.  Eventually when core dumps do contain this information this
function should only be used as a fall back for older core dumps.
---
 gdb/corelow.c             | 21 +++++++++++++++
 gdb/gdbarch-gen.h         |  9 +++++++
 gdb/gdbarch.c             | 32 +++++++++++++++++++++++
 gdb/gdbarch.h             |  1 +
 gdb/gdbarch_components.py | 11 ++++++++
 gdb/i387-tdep.c           | 55 +++++++++++++++++++++++++++++++++++++++
 gdb/i387-tdep.h           |  8 ++++++
 7 files changed, 137 insertions(+)

diff --git a/gdb/corelow.c b/gdb/corelow.c
index 46bb1077b6d..3d666a6d311 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -47,6 +47,7 @@
 #include "build-id.h"
 #include "gdbsupport/pathstuff.h"
 #include "gdbsupport/scoped_fd.h"
+#include "gdbsupport/x86-xstate.h"
 #include "debuginfod-support.h"
 #include <unordered_map>
 #include <unordered_set>
@@ -109,6 +110,8 @@ class core_target final : public process_stratum_target
   bool fetch_memtags (CORE_ADDR address, size_t len,
 		      gdb::byte_vector &tags, int type) override;
 
+  x86_xsave_layout fetch_x86_xsave_layout () override;
+
   /* A few helpers.  */
 
   /* Getter, see variable definition.  */
@@ -1387,6 +1390,24 @@ core_target::fetch_memtags (CORE_ADDR address, size_t len,
   return false;
 }
 
+/* Implementation of the "fetch_x86_xsave_layout" target_ops method.  */
+
+x86_xsave_layout
+core_target::fetch_x86_xsave_layout ()
+{
+  if (m_core_gdbarch != nullptr &&
+      gdbarch_core_read_x86_xsave_layout_p (m_core_gdbarch))
+    {
+      x86_xsave_layout layout;
+      if (!gdbarch_core_read_x86_xsave_layout (m_core_gdbarch, layout))
+	return {};
+
+      return layout;
+    }
+
+  return {};
+}
+
 /* Get a pointer to the current core target.  If not connected to a
    core target, return NULL.  */
 
diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
index 101b1b73636..d62eefa1c5b 100644
--- a/gdb/gdbarch-gen.h
+++ b/gdb/gdbarch-gen.h
@@ -1013,6 +1013,15 @@ typedef LONGEST (gdbarch_core_xfer_siginfo_ftype) (struct gdbarch *gdbarch, gdb_
 extern LONGEST gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
 extern void set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo);
 
+/* Read x86 XSAVE layout information from core file into XSAVE_LAYOUT.
+   Returns true if the layout was read successfully. */
+
+extern bool gdbarch_core_read_x86_xsave_layout_p (struct gdbarch *gdbarch);
+
+typedef bool (gdbarch_core_read_x86_xsave_layout_ftype) (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout);
+extern bool gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout);
+extern void set_gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, gdbarch_core_read_x86_xsave_layout_ftype *core_read_x86_xsave_layout);
+
 /* BFD target to use when generating a core file. */
 
 extern bool gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch);
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 30199a0b03d..1fc254d3d6e 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -182,6 +182,7 @@ struct gdbarch
   gdbarch_core_pid_to_str_ftype *core_pid_to_str = nullptr;
   gdbarch_core_thread_name_ftype *core_thread_name = nullptr;
   gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo = nullptr;
+  gdbarch_core_read_x86_xsave_layout_ftype *core_read_x86_xsave_layout = nullptr;
   const char * gcore_bfd_target = 0;
   int vtable_function_descriptors = 0;
   int vbit_in_delta = 0;
@@ -443,6 +444,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of core_pid_to_str, has predicate.  */
   /* Skip verify of core_thread_name, has predicate.  */
   /* Skip verify of core_xfer_siginfo, has predicate.  */
+  /* Skip verify of core_read_x86_xsave_layout, has predicate.  */
   /* Skip verify of gcore_bfd_target, has predicate.  */
   /* Skip verify of vtable_function_descriptors, invalid_p == 0 */
   /* Skip verify of vbit_in_delta, invalid_p == 0 */
@@ -1071,6 +1073,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   gdb_printf (file,
 	      "gdbarch_dump: core_xfer_siginfo = <%s>\n",
 	      host_address_to_string (gdbarch->core_xfer_siginfo));
+  gdb_printf (file,
+	      "gdbarch_dump: gdbarch_core_read_x86_xsave_layout_p() = %d\n",
+	      gdbarch_core_read_x86_xsave_layout_p (gdbarch));
+  gdb_printf (file,
+	      "gdbarch_dump: core_read_x86_xsave_layout = <%s>\n",
+	      host_address_to_string (gdbarch->core_read_x86_xsave_layout));
   gdb_printf (file,
 	      "gdbarch_dump: gdbarch_gcore_bfd_target_p() = %d\n",
 	      gdbarch_gcore_bfd_target_p (gdbarch));
@@ -3958,6 +3966,30 @@ set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch,
   gdbarch->core_xfer_siginfo = core_xfer_siginfo;
 }
 
+bool
+gdbarch_core_read_x86_xsave_layout_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->core_read_x86_xsave_layout != NULL;
+}
+
+bool
+gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->core_read_x86_xsave_layout != NULL);
+  if (gdbarch_debug >= 2)
+    gdb_printf (gdb_stdlog, "gdbarch_core_read_x86_xsave_layout called\n");
+  return gdbarch->core_read_x86_xsave_layout (gdbarch, xsave_layout);
+}
+
+void
+set_gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+					gdbarch_core_read_x86_xsave_layout_ftype core_read_x86_xsave_layout)
+{
+  gdbarch->core_read_x86_xsave_layout = core_read_x86_xsave_layout;
+}
+
 bool
 gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3d97919bc9b..a9d6a4b175c 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -57,6 +57,7 @@ struct syscalls_info;
 struct thread_info;
 struct ui_out;
 struct inferior;
+struct x86_xsave_layout;
 
 #include "regcache.h"
 
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
index 23e5789327c..846467b8d83 100644
--- a/gdb/gdbarch_components.py
+++ b/gdb/gdbarch_components.py
@@ -1709,6 +1709,17 @@ of bytes read (zero indicates EOF, a negative value indicates failure).
     predicate=True,
 )
 
+Method(
+    comment="""
+Read x86 XSAVE layout information from core file into XSAVE_LAYOUT.
+Returns true if the layout was read successfully.
+""",
+    type="bool",
+    name="core_read_x86_xsave_layout",
+    params=[("x86_xsave_layout &", "xsave_layout")],
+    predicate=True,
+)
+
 Value(
     comment="""
 BFD target to use when generating a core file.
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index df0a6058adc..f25579c1a9a 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -898,6 +898,61 @@ static int xsave_pkeys_offset[] =
   (xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
 
 
+/* See i387-tdep.h.  */
+
+bool
+i387_set_xsave_layout (uint64_t xcr0, size_t xsave_size,
+		       x86_xsave_layout &layout)
+{
+  if (HAS_PKRU (xcr0) && xsave_size == 2696)
+    {
+      /* Intel CPUs supporting PKRU.  */
+      layout.avx_offset = 576;
+      layout.bndregs_offset = 960;
+      layout.bndcfg_offset = 1024;
+      layout.k_offset = 1088;
+      layout.zmm_h_offset = 1152;
+      layout.zmm_offset = 1664;
+      layout.pkru_offset = 2688;
+    }
+  else if (HAS_PKRU (xcr0) && xsave_size == 2440)
+    {
+      /* AMD CPUs supporting PKRU.  */
+      layout.avx_offset = 576;
+      layout.k_offset = 832;
+      layout.zmm_h_offset = 896;
+      layout.zmm_offset = 1408;
+      layout.pkru_offset = 2432;
+    }
+  else if (HAS_AVX512 (xcr0) && xsave_size == 2688)
+    {
+      /* Intel CPUs supporting AVX512.  */
+      layout.avx_offset = 576;
+      layout.bndregs_offset = 960;
+      layout.bndcfg_offset = 1024;
+      layout.k_offset = 1088;
+      layout.zmm_h_offset = 1152;
+      layout.zmm_offset = 1664;
+    }
+  else if (HAS_MPX (xcr0) && xsave_size == 1088)
+    {
+      /* Intel CPUs supporting MPX.  */
+      layout.avx_offset = 576;
+      layout.bndregs_offset = 960;
+      layout.bndcfg_offset = 1024;
+    }
+  else if (HAS_AVX (xcr0) && xsave_size == 832)
+    {
+      /* Intel and AMD CPUs supporting AVX.  */
+      layout.avx_offset = 576;
+    }
+  else
+    return false;
+
+  layout.sizeof_xsave = xsave_size;
+  return true;
+}
+
 /* Extract from XSAVE a bitset of the features that are available on the
    target, but which have not yet been enabled.  */
 
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index 2e890e71a2b..b7674155255 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -25,6 +25,7 @@ class frame_info_ptr;
 struct regcache;
 struct type;
 struct ui_file;
+struct x86_xsave_layout;
 
 /* Number of i387 floating point registers.  */
 #define I387_NUM_REGS	16
@@ -138,6 +139,13 @@ extern void i387_collect_fsave (const struct regcache *regcache, int regnum,
 extern void i387_supply_fxsave (struct regcache *regcache, int regnum,
 				const void *fxsave);
 
+/* Select an XSAVE layout based on the XCR0 bitmask and total XSAVE
+   extended state size.  Returns true if the bitmask and size matched
+   a known layout.  */
+
+extern bool i387_set_xsave_layout (uint64_t xcr0, size_t xsave_size,
+				   x86_xsave_layout &layout);
+
 /* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
 
 extern void i387_supply_xsave (struct regcache *regcache, int regnum,
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 04/15] nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (2 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 03/15] core: Support fetching x86 XSAVE layout from architectures John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 19:41   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 05/15] x86 nat: Add helper functions to save the XSAVE layout for the host John Baldwin
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/nat/x86-cpuid.h | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/gdb/nat/x86-cpuid.h b/gdb/nat/x86-cpuid.h
index 0955afba577..517113d45e8 100644
--- a/gdb/nat/x86-cpuid.h
+++ b/gdb/nat/x86-cpuid.h
@@ -48,6 +48,30 @@ x86_cpuid (unsigned int __level,
   return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
 }
 
+/* Return cpuid data for requested cpuid level and sub-level, as found
+   in returned eax, ebx, ecx and edx registers.  The function checks
+   if cpuid is supported and returns 1 for valid cpuid information or
+   0 for unsupported cpuid level.  Pointers may be non-null.  */
+
+static __inline int
+x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
+		 unsigned int *__eax, unsigned int *__ebx,
+		 unsigned int *__ecx, unsigned int *__edx)
+{
+  unsigned int __scratch;
+
+  if (__eax == nullptr)
+    __eax = &__scratch;
+  if (__ebx == nullptr)
+    __ebx = &__scratch;
+  if (__ecx == nullptr)
+    __ecx = &__scratch;
+  if (__edx == nullptr)
+    __edx = &__scratch;
+
+  return __get_cpuid_count (__level, __sublevel, __eax, __ebx, __ecx, __edx);
+}
+
 #else
 
 static __inline int
@@ -58,6 +82,14 @@ x86_cpuid (unsigned int __level,
   return 0;
 }
 
+static __inline int
+x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
+		 unsigned int *__eax, unsigned int *__ebx,
+		 unsigned int *__ecx, unsigned int *__edx)
+{
+  return 0;
+}
+
 #endif /* i386 && x86_64 */
 
 #endif /* NAT_X86_CPUID_H */
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 05/15] x86 nat: Add helper functions to save the XSAVE layout for the host.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (3 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 04/15] nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 19:48   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts John Baldwin
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

x86_xsave_length returns the total length of the XSAVE state area
standard format as queried from CPUID.

x86_fetch_xsave_layout uses CPUID to query the offsets of XSAVE
extended regions from the running host.  The total length of the XSAVE
state area can either be supplied the caller if known (e.g. from
FreeBSD's PT_GETXSTATEINFO) or it can be queried from the running host
using x86_xsave_length.
---
 gdb/nat/x86-xstate.c | 67 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/nat/x86-xstate.h | 35 +++++++++++++++++++++++
 2 files changed, 102 insertions(+)
 create mode 100644 gdb/nat/x86-xstate.c
 create mode 100644 gdb/nat/x86-xstate.h

diff --git a/gdb/nat/x86-xstate.c b/gdb/nat/x86-xstate.c
new file mode 100644
index 00000000000..9fdc572356a
--- /dev/null
+++ b/gdb/nat/x86-xstate.c
@@ -0,0 +1,67 @@
+/* x86 XSAVE extended state functions.
+
+   Copyright (C) 2022-2023 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 "gdbsupport/x86-xstate.h"
+#include "nat/x86-cpuid.h"
+#include "nat/x86-xstate.h"
+
+/* Fetch the offset of a specific XSAVE extended region.  */
+
+static int
+xsave_feature_offset (uint64_t xcr0, int feature)
+{
+  uint32_t ebx;
+
+  if ((xcr0 & (1ULL << feature)) == 0)
+    return 0;
+
+  if (!x86_cpuid_count (0xd, feature, nullptr, &ebx, nullptr, nullptr))
+    return 0;
+  return ebx;
+}
+
+/* See x86-xstate.h.  */
+
+int
+x86_xsave_length ()
+{
+  uint32_t ecx;
+
+  if (!x86_cpuid_count (0xd, 0, nullptr, nullptr, &ecx, nullptr))
+    return 0;
+  return ecx;
+}
+
+/* See x86-xstate.h.  */
+
+x86_xsave_layout
+x86_fetch_xsave_layout (uint64_t xcr0, int len)
+{
+  x86_xsave_layout layout;
+  layout.sizeof_xsave = len;
+  layout.avx_offset = xsave_feature_offset (xcr0, X86_XSTATE_AVX_ID);
+  layout.bndregs_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDREGS_ID);
+  layout.bndcfg_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDCFG_ID);
+  layout.k_offset = xsave_feature_offset (xcr0, X86_XSTATE_K_ID);
+  layout.zmm_h_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_H_ID);
+  layout.zmm_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_ID);
+  layout.pkru_offset = xsave_feature_offset (xcr0, X86_XSTATE_PKRU_ID);
+  return layout;
+}
diff --git a/gdb/nat/x86-xstate.h b/gdb/nat/x86-xstate.h
new file mode 100644
index 00000000000..30f3a35087e
--- /dev/null
+++ b/gdb/nat/x86-xstate.h
@@ -0,0 +1,35 @@
+/* x86 XSAVE extended state functions.
+
+   Copyright (C) 2022-2023 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_XSTATE_H
+#define NAT_X86_XSTATE_H
+
+#include "gdbsupport/x86-xstate.h"
+
+/* Return the size of the XSAVE extended state fetched via CPUID.  */
+
+int x86_xsave_length ();
+
+/* Return the layout (size and offsets) of the XSAVE extended regions
+   for the running host.  Offsets of each of the enabled regions in
+   XCR0 are fetched via CPUID.  */
+
+x86_xsave_layout x86_fetch_xsave_layout (uint64_t xcr0, int len);
+
+#endif /* NAT_X86_XSTATE_H */
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (4 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 05/15] x86 nat: Add helper functions to save the XSAVE layout for the host John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 20:04   ` Simon Marchi
  2023-07-28 21:23   ` [PATCH v6a " John Baldwin
  2023-07-14 15:51 ` [PATCH v6 07/15] gdb: Support XSAVE layouts for the current host in the FreeBSD x86 targets John Baldwin
                   ` (10 subsequent siblings)
  16 siblings, 2 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

Refactor i386fbsd_core_read_xcr0 to fetch and return a corresponding
x86_xsave_layout as well as xcr0 using the size of an existing
NT_X86_XSTATE core dump to determine the offsets via
i387_set_xsave_layout.  Use this to add an implementation of
gdbarch_core_xfer_x86_xsave_layout.

Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
set and only fetch/store the register set if this size is non-zero.
---
 gdb/amd64-fbsd-tdep.c | 12 ++++++--
 gdb/i386-fbsd-tdep.c  | 72 ++++++++++++++++++++++++-------------------
 gdb/i386-fbsd-tdep.h  | 14 +++++++--
 3 files changed, 62 insertions(+), 36 deletions(-)

diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c
index 0d5ce004fb1..5dc519d7d6e 100644
--- a/gdb/amd64-fbsd-tdep.c
+++ b/gdb/amd64-fbsd-tdep.c
@@ -224,7 +224,9 @@ amd64fbsd_core_read_description (struct gdbarch *gdbarch,
 				 struct target_ops *target,
 				 bfd *abfd)
 {
-  return amd64_target_description (i386fbsd_core_read_xcr0 (abfd), true);
+  x86_xsave_layout layout;
+  return amd64_target_description (i386_fbsd_core_read_xsave_info (abfd, layout),
+				   true);
 }
 
 /* Similar to amd64_supply_fpregset, but use XSAVE extended state.  */
@@ -271,8 +273,10 @@ amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg-x86-segbases", AMD64_FBSD_SIZEOF_SEGBASES_REGSET,
       AMD64_FBSD_SIZEOF_SEGBASES_REGSET, &amd64_fbsd_segbases_regset,
       "segment bases", cb_data);
-  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
-      &amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
+  if (tdep->xsave_layout.sizeof_xsave != 0)
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &amd64fbsd_xstateregset,
+	"XSAVE extended state", cb_data);
 }
 
 /* Implement the get_thread_local_address gdbarch method.  */
@@ -313,6 +317,8 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tramp_frame_prepend_unwinder (gdbarch, &amd64_fbsd_sigframe);
 
   tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_fbsd_core_read_x86_xsave_layout);
 
   /* Iterate over core file register note sections.  */
   set_gdbarch_iterate_over_regset_sections
diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c
index fb9030413ab..df842f16bfc 100644
--- a/gdb/i386-fbsd-tdep.c
+++ b/gdb/i386-fbsd-tdep.c
@@ -18,13 +18,13 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "gdbcore.h"
 #include "osabi.h"
 #include "regcache.h"
 #include "regset.h"
 #include "trad-frame.h"
 #include "tramp-frame.h"
 #include "i386-fbsd-tdep.h"
-#include "gdbsupport/x86-xstate.h"
 
 #include "i386-tdep.h"
 #include "i387-tdep.h"
@@ -241,43 +241,49 @@ static const struct tramp_frame i386_fbsd64_sigframe =
   i386_fbsd_sigframe_init
 };
 
-/* Get XSAVE extended state xcr0 from core dump.  */
+/* See i386-fbsd-tdep.h.  */
 
 uint64_t
-i386fbsd_core_read_xcr0 (bfd *abfd)
+i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
 {
   asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
-  uint64_t xcr0;
+  if (xstate == nullptr)
+    return X86_XSTATE_SSE_MASK;
 
-  if (xstate)
+  /* Check extended state size.  */
+  size_t size = bfd_section_size (xstate);
+  if (size < X86_XSTATE_AVX_SIZE)
+    return X86_XSTATE_SSE_MASK;
+
+  char contents[8];
+  if (! bfd_get_section_contents (abfd, xstate, contents,
+				  I386_FBSD_XSAVE_XCR0_OFFSET, 8))
     {
-      size_t size = bfd_section_size (xstate);
-
-      /* Check extended state size.  */
-      if (size < X86_XSTATE_AVX_SIZE)
-	xcr0 = X86_XSTATE_SSE_MASK;
-      else
-	{
-	  char contents[8];
-
-	  if (! bfd_get_section_contents (abfd, xstate, contents,
-					  I386_FBSD_XSAVE_XCR0_OFFSET,
-					  8))
-	    {
-	      warning (_("Couldn't read `xcr0' bytes from "
-			 "`.reg-xstate' section in core file."));
-	      return X86_XSTATE_SSE_MASK;
-	    }
-
-	  xcr0 = bfd_get_64 (abfd, contents);
-	}
+      warning (_("Couldn't read `xcr0' bytes from "
+		 "`.reg-xstate' section in core file."));
+      return X86_XSTATE_SSE_MASK;
     }
-  else
-    xcr0 = X86_XSTATE_SSE_MASK;
+
+  uint64_t xcr0 = bfd_get_64 (abfd, contents);
+
+  if (!i387_set_xsave_layout (xcr0, size, layout))
+    return X86_XSTATE_SSE_MASK;
 
   return xcr0;
 }
 
+/* Implement the core_read_x86_xsave_layout gdbarch method.  */
+
+bool
+i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+				      x86_xsave_layout &layout)
+{
+  if (i386_fbsd_core_read_xsave_info (core_bfd, layout) == X86_XSTATE_SSE_MASK)
+    return false;
+
+  return true;
+}
+
 /* Implement the core_read_description gdbarch method.  */
 
 static const struct target_desc *
@@ -285,7 +291,9 @@ i386fbsd_core_read_description (struct gdbarch *gdbarch,
 				struct target_ops *target,
 				bfd *abfd)
 {
-  return i386_target_description (i386fbsd_core_read_xcr0 (abfd), true);
+  x86_xsave_layout layout;
+  return i386_target_description (i386_fbsd_core_read_xsave_info (abfd, layout),
+				  true);
 }
 
 /* Similar to i386_supply_fpregset, but use XSAVE extended state.  */
@@ -335,9 +343,9 @@ i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
       I386_FBSD_SIZEOF_SEGBASES_REGSET, &i386_fbsd_segbases_regset,
       "segment bases", cb_data);
 
-  if (tdep->xcr0 & X86_XSTATE_AVX)
-    cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
-	X86_XSTATE_SIZE (tdep->xcr0), &i386fbsd_xstateregset,
+  if (tdep->xsave_layout.sizeof_xsave != 0)
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &i386fbsd_xstateregset,
 	"XSAVE extended state", cb_data);
 }
 
@@ -386,6 +394,8 @@ i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   i386_elf_init_abi (info, gdbarch);
 
   tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_fbsd_core_read_x86_xsave_layout);
 
   /* Iterate over core file register note sections.  */
   set_gdbarch_iterate_over_regset_sections
diff --git a/gdb/i386-fbsd-tdep.h b/gdb/i386-fbsd-tdep.h
index cb991af9e49..cc2af4a0600 100644
--- a/gdb/i386-fbsd-tdep.h
+++ b/gdb/i386-fbsd-tdep.h
@@ -20,10 +20,20 @@
 #ifndef I386_FBSD_TDEP_H
 #define I386_FBSD_TDEP_H
 
+#include "gdbsupport/x86-xstate.h"
 #include "regset.h"
 
-/* Get XSAVE extended state xcr0 from core dump.  */
-extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd);
+/* Read the XSAVE extended state xcr0 value from the ABFD core file.
+   If it appears to be valid, return it and fill LAYOUT with values
+   inferred from that value.
+
+   Otherwise, return X86_XSTATE_SSE_MASK as a fallback and leave
+   LAYOUT untouched.  */
+uint64_t i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout);
+
+/* Implement the core_read_x86_xsave_layout gdbarch method.  */
+bool i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+					   x86_xsave_layout &layout);
 
 /* The format of the XSAVE extended area is determined by hardware.
    Cores store the XSAVE extended area in a NT_X86_XSTATE note that
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 07/15] gdb: Support XSAVE layouts for the current host in the FreeBSD x86 targets.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (5 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 20:26   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts John Baldwin
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

Use the CPUID instruction to fetch the offsets of supported state
components.
---
 gdb/amd64-fbsd-nat.c | 40 ++++++++++------------------------------
 gdb/configure.nat    |  5 +++--
 gdb/i386-fbsd-nat.c  | 39 +++++++++------------------------------
 gdb/x86-fbsd-nat.c   | 21 +++++++++++++++++++++
 gdb/x86-fbsd-nat.h   | 19 +++++++++++++++++++
 5 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c
index 43e83ff2485..5821d94e27e 100644
--- a/gdb/amd64-fbsd-nat.c
+++ b/gdb/amd64-fbsd-nat.c
@@ -31,9 +31,9 @@
 
 #include "amd64-tdep.h"
 #include "amd64-fbsd-tdep.h"
+#include "i387-tdep.h"
 #include "amd64-nat.h"
 #include "x86-nat.h"
-#include "gdbsupport/x86-xstate.h"
 #include "x86-fbsd-nat.h"
 
 class amd64_fbsd_nat_target final : public x86_fbsd_nat_target
@@ -47,10 +47,6 @@ class amd64_fbsd_nat_target final : public x86_fbsd_nat_target
 
 static amd64_fbsd_nat_target the_amd64_fbsd_nat_target;
 
-#ifdef PT_GETXSTATE_INFO
-static size_t xsave_len;
-#endif
-
 /* This is a layout of the amd64 'struct reg' but with i386
    registers.  */
 
@@ -146,9 +142,9 @@ amd64_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
      fetching the FPU/XSAVE state unnecessarily.  */
 
 #ifdef PT_GETXSTATE_INFO
-  if (xsave_len != 0)
+  if (m_xsave_info.xsave_len != 0)
     {
-      void *xstateregs = alloca (xsave_len);
+      void *xstateregs = alloca (m_xsave_info.xsave_len);
 
       if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
 	perror_with_name (_("Couldn't get extended state status"));
@@ -223,9 +219,9 @@ amd64_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
      fetching the FPU/XSAVE state unnecessarily.  */
 
 #ifdef PT_GETXSTATE_INFO
-  if (xsave_len != 0)
+  if (m_xsave_info.xsave_len != 0)
     {
-      void *xstateregs = alloca (xsave_len);
+      void *xstateregs = alloca (m_xsave_info.xsave_len);
 
       if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
 	perror_with_name (_("Couldn't get extended state status"));
@@ -233,7 +229,7 @@ amd64_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
       amd64_collect_xsave (regcache, regnum, xstateregs, 0);
 
       if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs,
-		  xsave_len) == -1)
+		  m_xsave_info.xsave_len) == -1)
 	perror_with_name (_("Couldn't write extended state status"));
       return;
     }
@@ -303,10 +299,6 @@ amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 const struct target_desc *
 amd64_fbsd_nat_target::read_description ()
 {
-#ifdef PT_GETXSTATE_INFO
-  static int xsave_probed;
-  static uint64_t xcr0;
-#endif
   struct reg regs;
   int is64;
 
@@ -318,25 +310,13 @@ amd64_fbsd_nat_target::read_description ()
     perror_with_name (_("Couldn't get registers"));
   is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL));
 #ifdef PT_GETXSTATE_INFO
-  if (!xsave_probed)
-    {
-      struct ptrace_xstate_info info;
-
-      if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
-		  (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
-	{
-	  xsave_len = info.xsave_len;
-	  xcr0 = info.xsave_mask;
-	}
-      xsave_probed = 1;
-    }
-
-  if (xsave_len != 0)
+  probe_xsave_layout (inferior_ptid.pid ());
+  if (m_xsave_info.xsave_len != 0)
     {
       if (is64)
-	return amd64_target_description (xcr0, true);
+	return amd64_target_description (m_xsave_info.xsave_mask, true);
       else
-	return i386_target_description (xcr0, true);
+	return i386_target_description (m_xsave_info.xsave_mask, true);
     }
 #endif
   if (is64)
diff --git a/gdb/configure.nat b/gdb/configure.nat
index aabcdeff989..b371ad89afe 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -166,7 +166,8 @@ case ${gdb_host} in
 	    i386)
 		# Host: FreeBSD/i386
 		NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
-		x86-bsd-nat.o x86-fbsd-nat.o i386-fbsd-nat.o bsd-kvm.o"
+		nat/x86-xstate.o x86-bsd-nat.o x86-fbsd-nat.o i386-fbsd-nat.o \
+		bsd-kvm.o"
 		;;
 	    mips)
 		# Host: FreeBSD/mips
@@ -195,7 +196,7 @@ case ${gdb_host} in
 		# Host: FreeBSD/amd64
 		NATDEPFILES="${NATDEPFILES} amd64-nat.o \
 		amd64-fbsd-nat.o bsd-kvm.o x86-nat.o nat/x86-dregs.o \
-		x86-bsd-nat.o x86-fbsd-nat.o"
+		nat/x86-xstate.o x86-bsd-nat.o x86-fbsd-nat.o"
 		;;
 	esac
 	;;
diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c
index a2255c3c26b..e2c0e611717 100644
--- a/gdb/i386-fbsd-nat.c
+++ b/gdb/i386-fbsd-nat.c
@@ -31,7 +31,6 @@
 #include "i386-fbsd-tdep.h"
 #include "i387-tdep.h"
 #include "x86-nat.h"
-#include "gdbsupport/x86-xstate.h"
 #include "x86-fbsd-nat.h"
 
 class i386_fbsd_nat_target final : public x86_fbsd_nat_target
@@ -47,10 +46,6 @@ class i386_fbsd_nat_target final : public x86_fbsd_nat_target
 
 static i386_fbsd_nat_target the_i386_fbsd_nat_target;
 
-#ifdef PT_GETXSTATE_INFO
-static size_t xsave_len;
-#endif
-
 static int have_ptrace_xmmregs;
 
 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
@@ -102,9 +97,9 @@ i386_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
      fetching the FPU/XSAVE state unnecessarily.  */
 
 #ifdef PT_GETXSTATE_INFO
-  if (xsave_len != 0)
+  if (m_xsave_info.xsave_len != 0)
     {
-      void *xstateregs = alloca (xsave_len);
+      void *xstateregs = alloca (m_xsave_info.xsave_len);
 
       if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
 	perror_with_name (_("Couldn't get extended state status"));
@@ -181,17 +176,17 @@ i386_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
      fetching the FPU/XSAVE state unnecessarily.  */
 
 #ifdef PT_GETXSTATE_INFO
-  if (xsave_len != 0)
+  if (m_xsave_info.xsave_len != 0)
     {
-      void *xstateregs = alloca (xsave_len);
+      void *xstateregs = alloca (m_xsave_info.xsave_len);
 
       if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
 	perror_with_name (_("Couldn't get extended state status"));
 
       i387_collect_xsave (regcache, regnum, xstateregs, 0);
 
-      if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, xsave_len)
-	  == -1)
+      if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs,
+		  m_xsave_info.xsave_len) == -1)
 	perror_with_name (_("Couldn't write extended state status"));
       return;
     }
@@ -309,31 +304,15 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 const struct target_desc *
 i386_fbsd_nat_target::read_description ()
 {
-#ifdef PT_GETXSTATE_INFO
-  static int xsave_probed;
-  static uint64_t xcr0;
-#endif
   static int xmm_probed;
 
   if (inferior_ptid == null_ptid)
     return this->beneath ()->read_description ();
 
 #ifdef PT_GETXSTATE_INFO
-  if (!xsave_probed)
-    {
-      struct ptrace_xstate_info info;
-
-      if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
-		  (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
-	{
-	  xsave_len = info.xsave_len;
-	  xcr0 = info.xsave_mask;
-	}
-      xsave_probed = 1;
-    }
-
-  if (xsave_len != 0)
-    return i386_target_description (xcr0, true);
+  probe_xsave_layout (inferior_ptid.pid ());
+  if (m_xsave_info.xsave_len != 0)
+    return i386_target_description (m_xsave_info.xsave_mask, true);
 #endif
 
   if (!xmm_probed)
diff --git a/gdb/x86-fbsd-nat.c b/gdb/x86-fbsd-nat.c
index 5d1c9fc7665..240e228976c 100644
--- a/gdb/x86-fbsd-nat.c
+++ b/gdb/x86-fbsd-nat.c
@@ -19,6 +19,9 @@
 
 #include "defs.h"
 #include "x86-fbsd-nat.h"
+#ifdef PT_GETXSTATE_INFO
+#include "nat/x86-xstate.h"
+#endif
 
 /* Implement the virtual fbsd_nat_target::low_new_fork method.  */
 
@@ -43,3 +46,21 @@ x86_fbsd_nat_target::low_new_fork (ptid_t parent, pid_t child)
   child_state = x86_debug_reg_state (child);
   *child_state = *parent_state;
 }
+
+#ifdef PT_GETXSTATE_INFO
+void
+x86_fbsd_nat_target::probe_xsave_layout (pid_t pid)
+{
+  if (m_xsave_probed)
+    return;
+
+  m_xsave_probed = true;
+
+  if (ptrace (PT_GETXSTATE_INFO, pid, (PTRACE_TYPE_ARG3) &m_xsave_info,
+	      sizeof (m_xsave_info)) != 0)
+    return;
+  if (m_xsave_info.xsave_len != 0)
+    m_xsave_layout = x86_fetch_xsave_layout (m_xsave_info.xsave_mask,
+					     m_xsave_info.xsave_len);
+}
+#endif
diff --git a/gdb/x86-fbsd-nat.h b/gdb/x86-fbsd-nat.h
index a424323f399..723bb6cf305 100644
--- a/gdb/x86-fbsd-nat.h
+++ b/gdb/x86-fbsd-nat.h
@@ -20,6 +20,11 @@
 #ifndef X86_FBSD_NAT_H
 #define X86_FBSD_NAT_H
 
+#include <sys/ptrace.h>
+
+#ifdef PT_GETXSTATE_INFO
+#include "gdbsupport/x86-xstate.h"
+#endif
 #include "fbsd-nat.h"
 #include "x86-bsd-nat.h"
 
@@ -32,6 +37,20 @@ class x86_fbsd_nat_target : public x86bsd_nat_target<fbsd_nat_target>
   { return true; }
 
   void low_new_fork (ptid_t parent, pid_t child) override;
+
+#ifdef PT_GETXSTATE_INFO
+  x86_xsave_layout fetch_x86_xsave_layout () override
+  { return m_xsave_layout; }
+
+protected:
+  void probe_xsave_layout (pid_t pid);
+
+  struct ptrace_xstate_info m_xsave_info;
+  x86_xsave_layout m_xsave_layout;
+
+private:
+  bool m_xsave_probed;
+#endif
 };
 
 #endif /* x86-bsd-nat.h */
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (6 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 07/15] gdb: Support XSAVE layouts for the current host in the FreeBSD x86 targets John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 20:45   ` Simon Marchi
  2023-07-28 21:29   ` [PATCH v6a " John Baldwin
  2023-07-14 15:51 ` [PATCH v6 09/15] gdb: Support XSAVE layouts for the current host in the Linux x86 targets John Baldwin
                   ` (8 subsequent siblings)
  16 siblings, 2 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

Refactor i386_linux_core_read_xcr0 to fetch and return a corresponding
x86_xsave_layout as well as xcr0 using the size of an existing
NT_X86_XSTATE core dump to determine the offsets via
i387_set_xsave_layout.  Use this to add an implementation of
gdbarch_core_xfer_x86_xsave_layout.

Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
set.
---
 gdb/amd64-linux-tdep.c | 11 +++++--
 gdb/i386-linux-tdep.c  | 67 ++++++++++++++++++++++++------------------
 gdb/i386-linux-tdep.h  | 25 +++++++++-------
 3 files changed, 61 insertions(+), 42 deletions(-)

diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index cbbac1a0c64..d51f4d5af53 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1616,7 +1616,8 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
 				  bfd *abfd)
 {
   /* Linux/x86-64.  */
-  uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
+  x86_xsave_layout layout;
+  uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
 
   return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
 				       gdbarch_ptr_bit (gdbarch) == 32);
@@ -1661,8 +1662,10 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 
   cb (".reg", 27 * 8, 27 * 8, &i386_gregset, NULL, cb_data);
   cb (".reg2", 512, 512, &amd64_fpregset, NULL, cb_data);
-  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
-      &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
+  if (tdep->xsave_layout.sizeof_xsave != 0)
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &amd64_linux_xstateregset,
+	"XSAVE extended state", cb_data);
 }
 
 /* The instruction sequences used in x86_64 machines for a
@@ -1804,6 +1807,8 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
   tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset);
 
   tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_linux_core_read_x86_xsave_layout);
 
   /* Add the %orig_rax register used for syscall restarting.  */
   set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc);
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 554c1455a5f..f27efbb1d59 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -638,45 +638,51 @@ static int i386_linux_sc_reg_offset[] =
   0 * 4				/* %gs */
 };
 
-/* Get XSAVE extended state xcr0 from core dump.  */
+/* See i386-linux-tdep.h.  */
 
 uint64_t
-i386_linux_core_read_xcr0 (bfd *abfd)
+i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
 {
   asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
-  uint64_t xcr0;
+  if (xstate == nullptr)
+    return X86_XSTATE_SSE_MASK;
 
-  if (xstate)
+  /* Check extended state size.  */
+  size_t size = bfd_section_size (xstate);
+  if (size < X86_XSTATE_AVX_SIZE)
+    return X86_XSTATE_SSE_MASK;
+
+  char contents[8];
+  if (! bfd_get_section_contents (abfd, xstate, contents,
+				  I386_LINUX_XSAVE_XCR0_OFFSET, 8))
     {
-      size_t size = bfd_section_size (xstate);
-
-      /* Check extended state size.  */
-      if (size < X86_XSTATE_AVX_SIZE)
-	xcr0 = X86_XSTATE_SSE_MASK;
-      else
-	{
-	  char contents[8];
-
-	  if (! bfd_get_section_contents (abfd, xstate, contents,
-					  I386_LINUX_XSAVE_XCR0_OFFSET,
-					  8))
-	    {
-	      warning (_("Couldn't read `xcr0' bytes from "
-			 "`.reg-xstate' section in core file."));
-	      return 0;
-	    }
-
-	  xcr0 = bfd_get_64 (abfd, contents);
-	}
+      warning (_("Couldn't read `xcr0' bytes from "
+		 "`.reg-xstate' section in core file."));
+      return X86_XSTATE_SSE_MASK;
     }
-  else
-    xcr0 = 0;
+
+  uint64_t xcr0 = bfd_get_64 (abfd, contents);
+
+  if (!i387_set_xsave_layout (xcr0, size, layout))
+    return X86_XSTATE_SSE_MASK;
 
   return xcr0;
 }
 
 /* See i386-linux-tdep.h.  */
 
+bool
+i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+				       x86_xsave_layout &layout)
+{
+  if (i386_linux_core_read_xsave_info (core_bfd, layout) == X86_XSTATE_SSE_MASK)
+    return false;
+
+  return true;
+}
+
+/* See i386-linux-tdep.h.  */
+
 const struct target_desc *
 i386_linux_read_description (uint64_t xcr0)
 {
@@ -708,7 +714,8 @@ i386_linux_core_read_description (struct gdbarch *gdbarch,
 				  bfd *abfd)
 {
   /* Linux/i386.  */
-  uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
+  x86_xsave_layout layout;
+  uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
   const struct target_desc *tdesc = i386_linux_read_description (xcr0);
 
   if (tdesc != NULL)
@@ -768,8 +775,8 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
 
   if (tdep->xcr0 & X86_XSTATE_AVX)
-    cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
-	X86_XSTATE_SIZE (tdep->xcr0), &i386_linux_xstateregset,
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &i386_linux_xstateregset,
 	"XSAVE extended state", cb_data);
   else if (tdep->xcr0 & X86_XSTATE_SSE)
     cb (".reg-xfp", 512, 512, &i386_fpregset, "extended floating-point",
@@ -872,6 +879,8 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
 
   tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_linux_core_read_x86_xsave_layout);
 
   set_gdbarch_process_record (gdbarch, i386_process_record);
   set_gdbarch_process_record_signal (gdbarch, i386_linux_record_signal);
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index c0fd1f7f300..66f08aae22d 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -20,6 +20,8 @@
 #ifndef I386_LINUX_TDEP_H
 #define I386_LINUX_TDEP_H
 
+#include "gdbsupport/x86-xstate.h"
+
 /* The Linux kernel pretends there is an additional "orig_eax"
    register.  Since GDB needs access to that register to be able to
    properly restart system calls when necessary (see
@@ -34,8 +36,18 @@
 /* Total number of registers for GNU/Linux.  */
 #define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1)
 
-/* Get XSAVE extended state xcr0 from core dump.  */
-extern uint64_t i386_linux_core_read_xcr0 (bfd *abfd);
+/* Read the XSAVE extended state xcr0 value from the ABFD core file.
+   If it appears to be valid, return it and fill LAYOUT with values
+   inferred from that value.
+
+   Otherwise, return X86_XSTATE_SSE_MASK as a fallback and leave
+   LAYOUT untouched.  */
+extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
+						 x86_xsave_layout &layout);
+
+/* Implement the core_read_x86_xsave_layout gdbarch method.  */
+extern bool i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+						   x86_xsave_layout &layout);
 
 /* Handle and display information related to the MPX bound violation
    to the user.  */
@@ -52,14 +64,7 @@ extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
 	  fxsave_bytes[0..463]
 	  sw_usable_bytes[464..511]
 	  xstate_hdr_bytes[512..575]
-	  avx_bytes[576..831]
-	  mpx_bytes [960..1032]
-	  avx512_k_regs[1088..1152]
-	  avx512_zmmh_regs0-7[1153..1407]
-	  avx512_zmmh_regs8-15[1408..1663]
-	  avx512_zmm_regs16-31[1664..2687]
-	  pkru[2688..2752]
-	  future_state etc
+	  extended state regions (AVX, MPX, AVX512, PKRU, etc.)
 	};
 
   Same memory layout will be used for the coredump NT_X86_XSTATE
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 09/15] gdb: Support XSAVE layouts for the current host in the Linux x86 targets.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (7 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-07-26 20:51   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 10/15] gdb: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

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.
---
 gdb/amd64-linux-nat.c | 6 ++++--
 gdb/configure.nat     | 3 ++-
 gdb/i386-linux-nat.c  | 8 ++++++--
 gdb/x86-linux-nat.c   | 3 +++
 gdb/x86-linux-nat.h   | 7 +++++++
 5 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index b5b0703879b..6571be40bb5 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -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;
diff --git a/gdb/configure.nat b/gdb/configure.nat
index b371ad89afe..2739d14a1c4 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -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"
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index a524fdc9a1d..7e0572e1907 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -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)
diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c
index ca4eaf5b645..cd8fd9c1dcd 100644
--- a/gdb/x86-linux-nat.c
+++ b/gdb/x86-linux-nat.c
@@ -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 ());
 	}
     }
 
diff --git a/gdb/x86-linux-nat.h b/gdb/x86-linux-nat.h
index fcb5f08d251..a99de6c29ea 100644
--- a/gdb/x86-linux-nat.h
+++ b/gdb/x86-linux-nat.h
@@ -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
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 10/15] gdb: Use x86_xstate_layout to parse the XSAVE extended state area.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (8 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 09/15] gdb: Support XSAVE layouts for the current host in the Linux x86 targets John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-08-28 16:34   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 11/15] gdbserver: Add a function to set the XSAVE mask and size John Baldwin
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

All of the tables describing the offsets of individual registers for
XSAVE state components now hold relative offsets rather than absolute
offsets.  Some tables (those for MPX registers and ZMMH registers) had
to be split into separate tables as they held entries that spanned
multiple state components.
---
 gdb/i387-tdep.c | 467 ++++++++++++++++++++++++++++--------------------
 gdb/i387-tdep.h |   1 +
 2 files changed, 278 insertions(+), 190 deletions(-)

diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index f25579c1a9a..389cf11bfbd 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -732,170 +732,204 @@ i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
 /* `xstate_bv' is at byte offset 512.  */
 #define XSAVE_XSTATE_BV_ADDR(xsave) (xsave + 512)
 
-/* At xsave_avxh_offset[REGNUM] you'll find the offset to the location in
-   the upper 128bit of AVX register data structure used by the "xsave"
-   instruction where GDB register REGNUM is stored.  */
+/* At xsave_avxh_offset[REGNUM] you'll find the relative offset within
+   the AVX region of the XSAVE extended state where the upper 128bits
+   of GDB register YMM0 + REGNUM is stored.  */
 
 static int xsave_avxh_offset[] =
 {
-  576 + 0 * 16,		/* Upper 128bit of %ymm0 through ...  */
-  576 + 1 * 16,
-  576 + 2 * 16,
-  576 + 3 * 16,
-  576 + 4 * 16,
-  576 + 5 * 16,
-  576 + 6 * 16,
-  576 + 7 * 16,
-  576 + 8 * 16,
-  576 + 9 * 16,
-  576 + 10 * 16,
-  576 + 11 * 16,
-  576 + 12 * 16,
-  576 + 13 * 16,
-  576 + 14 * 16,
-  576 + 15 * 16		/* Upper 128bit of ... %ymm15 (128 bits each).  */
+  0 * 16,		/* Upper 128bit of %ymm0 through ...  */
+  1 * 16,
+  2 * 16,
+  3 * 16,
+  4 * 16,
+  5 * 16,
+  6 * 16,
+  7 * 16,
+  8 * 16,
+  9 * 16,
+  10 * 16,
+  11 * 16,
+  12 * 16,
+  13 * 16,
+  14 * 16,
+  15 * 16		/* Upper 128bit of ... %ymm15 (128 bits each).  */
 };
 
-#define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
+#define XSAVE_AVXH_ADDR(tdep, xsave, regnum)			\
+  (xsave + (tdep)->xsave_layout.avx_offset			\
+   + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
 
-/* At xsave_ymm_avx512_offset[REGNUM] you'll find the offset to the location in
-   the upper 128bit of ZMM register data structure used by the "xsave"
-   instruction where GDB register REGNUM is stored.  */
+/* At xsave_ymm_avx512_offset[REGNUM] you'll find the relative offset
+   within the ZMM region of the XSAVE extended state where the second
+   128bits of GDB register YMM16 + REGNUM is stored.  */
 
 static int xsave_ymm_avx512_offset[] =
 {
-  /* HI16_ZMM_area + 16 bytes + regnum* 64 bytes.  */
-  1664 + 16 + 0 * 64,		/* %ymm16 through...  */
-  1664 + 16 + 1 * 64,
-  1664 + 16 + 2 * 64,
-  1664 + 16 + 3 * 64,
-  1664 + 16 + 4 * 64,
-  1664 + 16 + 5 * 64,
-  1664 + 16 + 6 * 64,
-  1664 + 16 + 7 * 64,
-  1664 + 16 + 8 * 64,
-  1664 + 16 + 9 * 64,
-  1664 + 16 + 10 * 64,
-  1664 + 16 + 11 * 64,
-  1664 + 16 + 12 * 64,
-  1664 + 16 + 13 * 64,
-  1664 + 16 + 14 * 64,
-  1664 + 16 + 15 * 64		/* ...  %ymm31 (128 bits each).  */
+  16 + 0 * 64,		/* %ymm16 through...  */
+  16 + 1 * 64,
+  16 + 2 * 64,
+  16 + 3 * 64,
+  16 + 4 * 64,
+  16 + 5 * 64,
+  16 + 6 * 64,
+  16 + 7 * 64,
+  16 + 8 * 64,
+  16 + 9 * 64,
+  16 + 10 * 64,
+  16 + 11 * 64,
+  16 + 12 * 64,
+  16 + 13 * 64,
+  16 + 14 * 64,
+  16 + 15 * 64		/* ...  %ymm31 (128 bits each).  */
 };
 
-#define XSAVE_YMM_AVX512_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_ymm_avx512_offset[regnum - I387_YMM16H_REGNUM (tdep)])
+#define XSAVE_YMM_AVX512_ADDR(tdep, xsave, regnum)			\
+  (xsave + (tdep)->xsave_layout.zmm_offset				\
+   + xsave_ymm_avx512_offset[regnum - I387_YMM16H_REGNUM (tdep)])
+
+/* At xsave_xmm_avx512_offset[REGNUM] you'll find the relative offset
+   within the ZMM region of the XSAVE extended state where the first
+   128bits of GDB register XMM16 + REGNUM is stored.  */
 
 static int xsave_xmm_avx512_offset[] =
 {
-  1664 + 0 * 64,		/* %ymm16 through...  */
-  1664 + 1 * 64,
-  1664 + 2 * 64,
-  1664 + 3 * 64,
-  1664 + 4 * 64,
-  1664 + 5 * 64,
-  1664 + 6 * 64,
-  1664 + 7 * 64,
-  1664 + 8 * 64,
-  1664 + 9 * 64,
-  1664 + 10 * 64,
-  1664 + 11 * 64,
-  1664 + 12 * 64,
-  1664 + 13 * 64,
-  1664 + 14 * 64,
-  1664 + 15 * 64		/* ...  %ymm31 (128 bits each).  */
+  0 * 64,			/* %xmm16 through...  */
+  1 * 64,
+  2 * 64,
+  3 * 64,
+  4 * 64,
+  5 * 64,
+  6 * 64,
+  7 * 64,
+  8 * 64,
+  9 * 64,
+  10 * 64,
+  11 * 64,
+  12 * 64,
+  13 * 64,
+  14 * 64,
+  15 * 64			/* ...  %xmm31 (128 bits each).  */
 };
 
-#define XSAVE_XMM_AVX512_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
+#define XSAVE_XMM_AVX512_ADDR(tdep, xsave, regnum)			\
+  (xsave + (tdep)->xsave_layout.zmm_offset				\
+   + xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
 
-static int xsave_mpx_offset[] = {
-  960 + 0 * 16,			/* bnd0r...bnd3r registers.  */
-  960 + 1 * 16,
-  960 + 2 * 16,
-  960 + 3 * 16,
-  1024 + 0 * 8,			/* bndcfg ... bndstatus.  */
-  1024 + 1 * 8,
+/* At xsave_bndregs_offset[REGNUM] you'll find the relative offset
+   within the BNDREGS region of the XSAVE extended state where the GDB
+   register BND0R + REGNUM is stored.  */
+
+static int xsave_bndregs_offset[] = {
+  0 * 16,			/* bnd0r...bnd3r registers.  */
+  1 * 16,
+  2 * 16,
+  3 * 16
+};
+
+#define XSAVE_BNDREGS_ADDR(tdep, xsave, regnum)				\
+  (xsave + (tdep)->xsave_layout.bndregs_offset				\
+   + xsave_bndregs_offset[regnum - I387_BND0R_REGNUM (tdep)])
+
+static int xsave_bndcfg_offset[] = {
+  0 * 8,			/* bndcfg ... bndstatus.  */
+  1 * 8,
 };
 
-#define XSAVE_MPX_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_mpx_offset[regnum - I387_BND0R_REGNUM (tdep)])
+#define XSAVE_BNDCFG_ADDR(tdep, xsave, regnum)			\
+  (xsave + (tdep)->xsave_layout.bndcfg_offset			\
+   + xsave_bndcfg_offset[regnum - I387_BNDCFGU_REGNUM (tdep)])
 
-  /* At xsave_avx512__h_offset[REGNUM] you find the offset to the location
-   of the AVX512 opmask register data structure used by the "xsave"
-   instruction where GDB register REGNUM is stored.  */
+/* At xsave_avx512_k_offset[REGNUM] you'll find the relative offset
+   within the K region of the XSAVE extended state where the AVX512
+   opmask register K0 + REGNUM is stored.  */
 
 static int xsave_avx512_k_offset[] =
 {
-  1088 + 0 * 8,			/* %k0 through...  */
-  1088 + 1 * 8,
-  1088 + 2 * 8,
-  1088 + 3 * 8,
-  1088 + 4 * 8,
-  1088 + 5 * 8,
-  1088 + 6 * 8,
-  1088 + 7 * 8     		/* %k7 (64 bits each).  */
+  0 * 8,			/* %k0 through...  */
+  1 * 8,
+  2 * 8,
+  3 * 8,
+  4 * 8,
+  5 * 8,
+  6 * 8,
+  7 * 8				/* %k7 (64 bits each).	*/
 };
 
-#define XSAVE_AVX512_K_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_avx512_k_offset[regnum - I387_K0_REGNUM (tdep)])
+#define XSAVE_AVX512_K_ADDR(tdep, xsave, regnum)		\
+  (xsave + (tdep)->xsave_layout.k_offset			\
+   + xsave_avx512_k_offset[regnum - I387_K0_REGNUM (tdep)])
 
-/* At xsave_avx512_zmm_h_offset[REGNUM] you find the offset to the location in
-   the upper 256bit of AVX512 ZMMH register data structure used by the "xsave"
-   instruction where GDB register REGNUM is stored.  */
 
-static int xsave_avx512_zmm_h_offset[] =
+/* At xsave_avx512_zmm0_h_offset[REGNUM] you find the relative offset
+   within the ZMM_H region of the XSAVE extended state where the upper
+   256bits of the GDB register ZMM0 + REGNUM is stored.  */
+
+static int xsave_avx512_zmm0_h_offset[] =
+{
+  0 * 32,		/* Upper 256bit of %zmmh0 through...  */
+  1 * 32,
+  2 * 32,
+  3 * 32,
+  4 * 32,
+  5 * 32,
+  6 * 32,
+  7 * 32,
+  8 * 32,
+  9 * 32,
+  10 * 32,
+  11 * 32,
+  12 * 32,
+  13 * 32,
+  14 * 32,
+  15 * 32		/* Upper 256bit of...  %zmmh15 (256 bits each).  */
+};
+
+#define XSAVE_AVX512_ZMM0_H_ADDR(tdep, xsave, regnum)			\
+  (xsave + (tdep)->xsave_layout.zmm_h_offset				\
+   + xsave_avx512_zmm0_h_offset[regnum - I387_ZMM0H_REGNUM (tdep)])
+
+/* At xsave_avx512_zmm16_h_offset[REGNUM] you find the relative offset
+   within the ZMM_H region of the XSAVE extended state where the upper
+   256bits of the GDB register ZMM16 + REGNUM is stored.  */
+
+static int xsave_avx512_zmm16_h_offset[] =
 {
-  1152 + 0 * 32,
-  1152 + 1 * 32,	/* Upper 256bit of %zmmh0 through...  */
-  1152 + 2 * 32,
-  1152 + 3 * 32,
-  1152 + 4 * 32,
-  1152 + 5 * 32,
-  1152 + 6 * 32,
-  1152 + 7 * 32,
-  1152 + 8 * 32,
-  1152 + 9 * 32,
-  1152 + 10 * 32,
-  1152 + 11 * 32,
-  1152 + 12 * 32,
-  1152 + 13 * 32,
-  1152 + 14 * 32,
-  1152 + 15 * 32,	/* Upper 256bit of...  %zmmh15 (256 bits each).  */
-  1664 + 32 + 0 * 64,   /* Upper 256bit of...  %zmmh16 (256 bits each).  */
-  1664 + 32 + 1 * 64,
-  1664 + 32 + 2 * 64,
-  1664 + 32 + 3 * 64,
-  1664 + 32 + 4 * 64,
-  1664 + 32 + 5 * 64,
-  1664 + 32 + 6 * 64,
-  1664 + 32 + 7 * 64,
-  1664 + 32 + 8 * 64,
-  1664 + 32 + 9 * 64,
-  1664 + 32 + 10 * 64,
-  1664 + 32 + 11 * 64,
-  1664 + 32 + 12 * 64,
-  1664 + 32 + 13 * 64,
-  1664 + 32 + 14 * 64,
-  1664 + 32 + 15 * 64   /* Upper 256bit of... %zmmh31 (256 bits each).  */
+  32 + 0 * 64,		/* Upper 256bit of...  %zmmh16 (256 bits each).  */
+  32 + 1 * 64,
+  32 + 2 * 64,
+  32 + 3 * 64,
+  32 + 4 * 64,
+  32 + 5 * 64,
+  32 + 6 * 64,
+  32 + 7 * 64,
+  32 + 8 * 64,
+  32 + 9 * 64,
+  32 + 10 * 64,
+  32 + 11 * 64,
+  32 + 12 * 64,
+  32 + 13 * 64,
+  32 + 14 * 64,
+  32 + 15 * 64		/* Upper 256bit of... %zmmh31 (256 bits each).  */
 };
 
-#define XSAVE_AVX512_ZMM_H_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_avx512_zmm_h_offset[regnum - I387_ZMM0H_REGNUM (tdep)])
+#define XSAVE_AVX512_ZMM16_H_ADDR(tdep, xsave, regnum)			\
+  (xsave + (tdep)->xsave_layout.zmm_offset				\
+   + xsave_avx512_zmm16_h_offset[regnum - I387_ZMM16H_REGNUM (tdep)])
 
-/* At xsave_pkeys_offset[REGNUM] you find the offset to the location
-   of the PKRU register data structure used by the "xsave"
-   instruction where GDB register REGNUM is stored.  */
+/* At xsave_pkeys_offset[REGNUM] you'll find the relative offset
+   within the PKEYS region of the XSAVE extended state where the PKRU
+   register is stored.  */
 
 static int xsave_pkeys_offset[] =
 {
-2688 + 0 * 8		/* %pkru (64 bits in XSTATE, 32-bit actually used by
+  0 * 8			/* %pkru (64 bits in XSTATE, 32-bit actually used by
 			   instructions and applications).  */
 };
 
-#define XSAVE_PKEYS_ADDR(tdep, xsave, regnum) \
-  (xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
+#define XSAVE_PKEYS_ADDR(tdep, xsave, regnum)				\
+  (xsave + (tdep)->xsave_layout.pkru_offset				\
+   + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
 
 
 /* See i387-tdep.h.  */
@@ -998,14 +1032,16 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
       x87 = 0x1,
       sse = 0x2,
       avxh = 0x4,
-      mpx  = 0x8,
-      avx512_k = 0x10,
-      avx512_zmm_h = 0x20,
-      avx512_ymmh_avx512 = 0x40,
-      avx512_xmm_avx512 = 0x80,
-      pkeys = 0x100,
-      all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
-	    | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
+      bndregs = 0x8,
+      bndcfg = 0x10,
+      avx512_k = 0x20,
+      avx512_zmm0_h = 0x40,
+      avx512_zmm16_h = 0x80,
+      avx512_ymmh_avx512 = 0x100,
+      avx512_xmm_avx512 = 0x200,
+      pkeys = 0x400,
+      all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
+	    | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
     } regclass;
 
   gdb_assert (regs != NULL);
@@ -1018,8 +1054,11 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	   && regnum < I387_PKEYSEND_REGNUM (tdep))
     regclass = pkeys;
   else if (regnum >= I387_ZMM0H_REGNUM (tdep)
+	   && regnum < I387_ZMM16H_REGNUM (tdep))
+    regclass = avx512_zmm0_h;
+  else if (regnum >= I387_ZMM16H_REGNUM (tdep)
 	   && regnum < I387_ZMMENDH_REGNUM (tdep))
-    regclass = avx512_zmm_h;
+    regclass = avx512_zmm16_h;
   else if (regnum >= I387_K0_REGNUM (tdep)
 	   && regnum < I387_KEND_REGNUM (tdep))
     regclass = avx512_k;
@@ -1033,8 +1072,11 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	   && regnum < I387_YMMENDH_REGNUM (tdep))
     regclass = avxh;
   else if (regnum >= I387_BND0R_REGNUM (tdep)
+	   && regnum < I387_BNDCFGU_REGNUM (tdep))
+    regclass = bndregs;
+  else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
 	   && regnum < I387_MPXEND_REGNUM (tdep))
-    regclass = mpx;
+    regclass = bndcfg;
   else if (regnum >= I387_XMM0_REGNUM (tdep)
 	   && regnum < I387_MXCSR_REGNUM (tdep))
     regclass = sse;
@@ -1067,13 +1109,20 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	regcache->raw_supply (regnum, XSAVE_PKEYS_ADDR (tdep, regs, regnum));
       return;
 
-    case avx512_zmm_h:
-      if ((clear_bv & (regnum < zmm_endlo_regnum ? X86_XSTATE_ZMM_H
-						 : X86_XSTATE_ZMM)))
+    case avx512_zmm0_h:
+      if ((clear_bv & X86_XSTATE_ZMM_H))
 	regcache->raw_supply (regnum, zero);
       else
 	regcache->raw_supply (regnum,
-			      XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum));
+			      XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, regnum));
+      return;
+
+    case avx512_zmm16_h:
+      if ((clear_bv & X86_XSTATE_ZMM))
+	regcache->raw_supply (regnum, zero);
+      else
+	regcache->raw_supply (regnum,
+			      XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, regnum));
       return;
 
     case avx512_k:
@@ -1106,11 +1155,18 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	regcache->raw_supply (regnum, XSAVE_AVXH_ADDR (tdep, regs, regnum));
       return;
 
-    case mpx:
+    case bndcfg:
+      if ((clear_bv & X86_XSTATE_BNDCFG))
+	regcache->raw_supply (regnum, zero);
+      else
+	regcache->raw_supply (regnum, XSAVE_BNDCFG_ADDR (tdep, regs, regnum));
+      return;
+
+    case bndregs:
       if ((clear_bv & X86_XSTATE_BNDREGS))
 	regcache->raw_supply (regnum, zero);
       else
-	regcache->raw_supply (regnum, XSAVE_MPX_ADDR (tdep, regs, regnum));
+	regcache->raw_supply (regnum, XSAVE_BNDREGS_ADDR (tdep, regs, regnum));
       return;
 
     case sse:
@@ -1159,7 +1215,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    {
 	      for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
 		regcache->raw_supply (i,
-				      XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i));
+				      XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i));
 	    }
 	}
 
@@ -1187,7 +1243,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	{
 	  if ((clear_bv & X86_XSTATE_ZMM))
 	    {
-	      for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
+	      for (i = I387_ZMM16H_REGNUM (tdep);
+		   i < I387_ZMMENDH_REGNUM (tdep); i++)
 		regcache->raw_supply (i, zero);
 	      for (i = I387_YMM16H_REGNUM (tdep);
 		   i < I387_YMMH_AVX512_END_REGNUM (tdep);
@@ -1200,9 +1257,10 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    }
 	  else
 	    {
-	      for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
+	      for (i = I387_ZMM16H_REGNUM (tdep);
+		   i < I387_ZMMENDH_REGNUM (tdep); i++)
 		regcache->raw_supply (i,
-				      XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i));
+				      XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, i));
 	      for (i = I387_YMM16H_REGNUM (tdep);
 		   i < I387_YMMH_AVX512_END_REGNUM (tdep);
 		   i++)
@@ -1245,7 +1303,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    {
 	      for (i = I387_BND0R_REGNUM (tdep);
 		   i < I387_BNDCFGU_REGNUM (tdep); i++)
-		regcache->raw_supply (i, XSAVE_MPX_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_BNDREGS_ADDR (tdep, regs, i));
 	    }
 	}
 
@@ -1262,7 +1320,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
 	    {
 	      for (i = I387_BNDCFGU_REGNUM (tdep);
 		   i < I387_MPXEND_REGNUM (tdep); i++)
-		regcache->raw_supply (i, XSAVE_MPX_ADDR (tdep, regs, i));
+		regcache->raw_supply (i, XSAVE_BNDCFG_ADDR (tdep, regs, i));
 	    }
 	}
 
@@ -1418,14 +1476,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
       x87 = 0x2,
       sse = 0x4,
       avxh = 0x8,
-      mpx  = 0x10,
-      avx512_k = 0x20,
-      avx512_zmm_h = 0x40,
-      avx512_ymmh_avx512 = 0x80,
-      avx512_xmm_avx512 = 0x100,
-      pkeys = 0x200,
-      all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
-	    | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
+      bndregs = 0x10,
+      bndcfg = 0x20,
+      avx512_k = 0x40,
+      avx512_zmm0_h = 0x80,
+      avx512_zmm16_h = 0x100,
+      avx512_ymmh_avx512 = 0x200,
+      avx512_xmm_avx512 = 0x400,
+      pkeys = 0x800,
+      all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
+	    | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
     } regclass;
 
   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
@@ -1437,8 +1497,11 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	   && regnum < I387_PKEYSEND_REGNUM (tdep))
     regclass = pkeys;
   else if (regnum >= I387_ZMM0H_REGNUM (tdep)
+	   && regnum < I387_ZMM16H_REGNUM (tdep))
+    regclass = avx512_zmm0_h;
+  else if (regnum >= I387_ZMM16H_REGNUM (tdep)
 	   && regnum < I387_ZMMENDH_REGNUM (tdep))
-    regclass = avx512_zmm_h;
+    regclass = avx512_zmm16_h;
   else if (regnum >= I387_K0_REGNUM (tdep)
 	   && regnum < I387_KEND_REGNUM (tdep))
     regclass = avx512_k;
@@ -1452,8 +1515,11 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	   && regnum < I387_YMMENDH_REGNUM (tdep))
     regclass = avxh;
   else if (regnum >= I387_BND0R_REGNUM (tdep)
+	   && regnum < I387_BNDCFGU_REGNUM (tdep))
+    regclass = bndregs;
+  else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
 	   && regnum < I387_MPXEND_REGNUM (tdep))
-    regclass = mpx;
+    regclass = bndcfg;
   else if (regnum >= I387_XMM0_REGNUM (tdep)
 	   && regnum < I387_MXCSR_REGNUM (tdep))
     regclass = sse;
@@ -1470,7 +1536,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
   if (gcore)
     {
       /* Clear XSAVE extended state.  */
-      memset (regs, 0, X86_XSTATE_SIZE (tdep->xcr0));
+      memset (regs, 0, tdep->xsave_layout.sizeof_xsave);
 
       /* Update XCR0 and `xstate_bv' with XCR0 for gcore.  */
       if (tdep->xsave_xcr0_offset != -1)
@@ -1505,16 +1571,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
       if ((clear_bv & X86_XSTATE_BNDREGS))
 	for (i = I387_BND0R_REGNUM (tdep);
 	     i < I387_BNDCFGU_REGNUM (tdep); i++)
-	  memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 16);
+	  memset (XSAVE_BNDREGS_ADDR (tdep, regs, i), 0, 16);
 
       if ((clear_bv & X86_XSTATE_BNDCFG))
 	for (i = I387_BNDCFGU_REGNUM (tdep);
 	     i < I387_MPXEND_REGNUM (tdep); i++)
-	  memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8);
+	  memset (XSAVE_BNDCFG_ADDR (tdep, regs, i), 0, 8);
 
       if ((clear_bv & X86_XSTATE_ZMM_H))
 	for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
-	  memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
+	  memset (XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i), 0, 32);
 
       if ((clear_bv & X86_XSTATE_K))
 	for (i = I387_K0_REGNUM (tdep);
@@ -1523,8 +1589,9 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 
       if ((clear_bv & X86_XSTATE_ZMM))
 	{
-	  for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
-	    memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
+	  for (i = I387_ZMM16H_REGNUM (tdep); i < I387_ZMMENDH_REGNUM (tdep);
+	       i++)
+	    memset (XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, i), 0, 32);
 	  for (i = I387_YMM16H_REGNUM (tdep);
 	       i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
 	    memset (XSAVE_YMM_AVX512_ADDR (tdep, regs, i), 0, 16);
@@ -1587,15 +1654,27 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	  }
 
       /* Check if any ZMMH registers are changed.  */
-      if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM)))
-	for (i = I387_ZMM0H_REGNUM (tdep);
+      if ((tdep->xcr0 & X86_XSTATE_ZMM))
+	for (i = I387_ZMM16H_REGNUM (tdep);
 	     i < I387_ZMMENDH_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i);
+	    p = XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, i);
 	    if (memcmp (raw, p, 32) != 0)
 	      {
-		xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
+		xstate_bv |= X86_XSTATE_ZMM;
+		memcpy (p, raw, 32);
+	      }
+	  }
+
+      if ((tdep->xcr0 & X86_XSTATE_ZMM_H))
+	for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
+	  {
+	    regcache->raw_collect (i, raw);
+	    p = XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i);
+	    if (memcmp (raw, p, 32) != 0)
+	      {
+		xstate_bv |= X86_XSTATE_ZMM_H;
 		memcpy (p, raw, 32);
 	      }
 	  }
@@ -1647,7 +1726,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	     i < I387_BNDCFGU_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_MPX_ADDR (tdep, regs, i);
+	    p = XSAVE_BNDREGS_ADDR (tdep, regs, i);
 	    if (memcmp (raw, p, 16))
 	      {
 		xstate_bv |= X86_XSTATE_BNDREGS;
@@ -1661,7 +1740,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	     i < I387_MPXEND_REGNUM (tdep); i++)
 	  {
 	    regcache->raw_collect (i, raw);
-	    p = XSAVE_MPX_ADDR (tdep, regs, i);
+	    p = XSAVE_BNDCFG_ADDR (tdep, regs, i);
 	    if (memcmp (raw, p, 8))
 	      {
 		xstate_bv |= X86_XSTATE_BNDCFG;
@@ -1750,15 +1829,26 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	    }
 	  break;
 
-	case avx512_zmm_h:
-	  /* This is a ZMM register.  */
-	  p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum);
+	case avx512_zmm16_h:
+	  /* This is a ZMM16-31 register.  */
+	  p = XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, regnum);
 	  if (memcmp (raw, p, 32) != 0)
 	    {
-	      xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
+	      xstate_bv |= X86_XSTATE_ZMM;
 	      memcpy (p, raw, 32);
 	    }
 	  break;
+
+	case avx512_zmm0_h:
+	  /* This is a ZMM0-15 register.  */
+	  p = XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 32) != 0)
+	    {
+	      xstate_bv |= X86_XSTATE_ZMM_H;
+	      memcpy (p, raw, 32);
+	    }
+	  break;
+
 	case avx512_k:
 	  /* This is a AVX512 mask register.  */
 	  p = XSAVE_AVX512_K_ADDR (tdep, regs, regnum);
@@ -1799,25 +1889,22 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
 	    }
 	  break;
 
-	case mpx:
-	  if (regnum < I387_BNDCFGU_REGNUM (tdep))
+	case bndregs:
+	  regcache->raw_collect (regnum, raw);
+	  p = XSAVE_BNDREGS_ADDR (tdep, regs, regnum);
+	  if (memcmp (raw, p, 16))
 	    {
-	      regcache->raw_collect (regnum, raw);
-	      p = XSAVE_MPX_ADDR (tdep, regs, regnum);
-	      if (memcmp (raw, p, 16))
-		{
-		  xstate_bv |= X86_XSTATE_BNDREGS;
-		  memcpy (p, raw, 16);
-		}
-	    }
-	  else
-	    {
-	      p = XSAVE_MPX_ADDR (tdep, regs, regnum);
-	      xstate_bv |= X86_XSTATE_BNDCFG;
-	      memcpy (p, raw, 8);
+	      xstate_bv |= X86_XSTATE_BNDREGS;
+	      memcpy (p, raw, 16);
 	    }
 	  break;
 
+	case bndcfg:
+	  p = XSAVE_BNDCFG_ADDR (tdep, regs, regnum);
+	  xstate_bv |= X86_XSTATE_BNDCFG;
+	  memcpy (p, raw, 8);
+	  break;
+
 	case sse:
 	  /* This is an SSE register.  */
 	  p = FXSAVE_ADDR (tdep, regs, regnum);
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index b7674155255..55651a497df 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -51,6 +51,7 @@ struct x86_xsave_layout;
 #define I387_K0_REGNUM(tdep) ((tdep)->k0_regnum)
 #define I387_NUM_ZMMH_REGS(tdep) ((tdep)->num_zmm_regs)
 #define I387_ZMM0H_REGNUM(tdep) ((tdep)->zmm0h_regnum)
+#define I387_ZMM16H_REGNUM(tdep) ((tdep)->zmm0h_regnum + 16)
 #define I387_NUM_YMM_AVX512_REGS(tdep) ((tdep)->num_ymm_avx512_regs)
 #define I387_YMM16H_REGNUM(tdep) ((tdep)->ymm16h_regnum)
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 11/15] gdbserver: Add a function to set the XSAVE mask and size.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (9 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 10/15] gdb: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-08-28 16:46   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 12/15] gdbserver: Refactor the legacy region within the xsave struct John Baldwin
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

Make x86_xcr0 private to i387-fp.cc and use i387_set_xsave_mask to set
the value instead.  Add a static global instance of x86_xsave_layout
and initialize it in the new function as well to be used in a future
commit to parse XSAVE extended state regions.

Update the Linux port to use this function rather than setting
x86_xcr0 directly.  In the case that XML is not supported, don't
bother setting x86_xcr0 to the default value but just omit the call to
i387_set_xsave_mask as i387-fp.cc defaults to the SSE case used for
non-XML.

In addition, use x86_xsave_length to determine the size of the XSAVE
register set via CPUID.
---
 gdbserver/configure.srv    | 12 ++++++++----
 gdbserver/i387-fp.cc       | 16 ++++++++++++++--
 gdbserver/i387-fp.h        |  4 +++-
 gdbserver/linux-x86-low.cc | 10 ++++++----
 4 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv
index f0101994529..72256f82871 100644
--- a/gdbserver/configure.srv
+++ b/gdbserver/configure.srv
@@ -102,7 +102,8 @@ case "${gdbserver_host}" in
   i[34567]86-*-linux*)	srv_tgtobj="${srv_tgtobj} arch/i386.o"
 			srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
 			srv_tgtobj="${srv_tgtobj} linux-x86-low.o x86-low.o"
-			srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o i387-fp.o"
+			srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o"
+			srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
 			srv_tgtobj="${srv_tgtobj} linux-x86-tdesc.o"
 			srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
 			srv_tgtobj="${srv_tgtobj} nat/x86-linux.o"
@@ -362,7 +363,8 @@ case "${gdbserver_host}" in
 			srv_linux_thread_db=yes
 			;;
   x86_64-*-linux*)	srv_tgtobj="$srv_linux_obj linux-x86-low.o x86-low.o"
-			srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o i387-fp.o"
+			srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o"
+			srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
 			srv_tgtobj="${srv_tgtobj} arch/i386.o arch/amd64.o"
 			srv_tgtobj="${srv_tgtobj} linux-x86-tdesc.o"
 			srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
@@ -377,14 +379,16 @@ case "${gdbserver_host}" in
 			ipa_obj="${ipa_obj} arch/amd64-ipa.o"
 			;;
   x86_64-*-mingw*)	srv_regobj=""
-			srv_tgtobj="x86-low.o nat/x86-dregs.o i387-fp.o"
+			srv_tgtobj="x86-low.o nat/x86-dregs.o"
+			srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
 			srv_tgtobj="${srv_tgtobj} win32-low.o win32-i386-low.o"
 			srv_tgtobj="${srv_tgtobj} nat/windows-nat.o"
 			srv_tgtobj="${srv_tgtobj} arch/amd64.o arch/i386.o"
 			srv_mingw=yes
 			;;
   x86_64-*-cygwin*)	srv_regobj=""
-			srv_tgtobj="x86-low.o nat/x86-dregs.o i387-fp.o"
+			srv_tgtobj="x86-low.o nat/x86-dregs.o"
+			srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
 			srv_tgtobj="${srv_tgtobj} win32-low.o win32-i386-low.o"
 			srv_tgtobj="${srv_tgtobj} nat/windows-nat.o"
 			srv_tgtobj="${srv_tgtobj} arch/amd64.o arch/i386.o"
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
index 49795ace9a9..b8d7a912f26 100644
--- a/gdbserver/i387-fp.cc
+++ b/gdbserver/i387-fp.cc
@@ -19,12 +19,18 @@
 #include "server.h"
 #include "i387-fp.h"
 #include "gdbsupport/x86-xstate.h"
+#include "nat/x86-xstate.h"
+
+/* Default to SSE.  */
+static unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
 
 static const int num_mpx_bnd_registers = 4;
 static const int num_mpx_cfg_registers = 2;
 static const int num_avx512_k_registers = 8;
 static const int num_pkeys_registers = 1;
 
+static x86_xsave_layout xsave_layout;
+
 /* Note: These functions preserve the reserved bits in control registers.
    However, gdbserver promptly throws away that information.  */
 
@@ -974,5 +980,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
     }
 }
 
-/* Default to SSE.  */
-unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
+/* See i387-fp.h.  */
+
+void
+i387_set_xsave_mask (uint64_t xcr0, int len)
+{
+  x86_xcr0 = xcr0;
+  xsave_layout = x86_fetch_xsave_layout (xcr0, len);
+}
diff --git a/gdbserver/i387-fp.h b/gdbserver/i387-fp.h
index f536a2be15a..09b6a91aa25 100644
--- a/gdbserver/i387-fp.h
+++ b/gdbserver/i387-fp.h
@@ -28,6 +28,8 @@ void i387_fxsave_to_cache (struct regcache *regcache, const void *buf);
 void i387_cache_to_xsave (struct regcache *regcache, void *buf);
 void i387_xsave_to_cache (struct regcache *regcache, const void *buf);
 
-extern unsigned long long x86_xcr0;
+/* Set the XSAVE mask and fetch the XSAVE layout via CPUID.  */
+
+void i387_set_xsave_mask (uint64_t xcr0, int len);
 
 #endif /* GDBSERVER_I387_FP_H */
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
index 4a538b107be..1483e2a66d7 100644
--- a/gdbserver/linux-x86-low.cc
+++ b/gdbserver/linux-x86-low.cc
@@ -25,6 +25,7 @@
 #include "i387-fp.h"
 #include "x86-low.h"
 #include "gdbsupport/x86-xstate.h"
+#include "nat/x86-xstate.h"
 #include "nat/gdb_ptrace.h"
 
 #ifdef __x86_64__
@@ -873,6 +874,7 @@ x86_linux_read_description (void)
   int xcr0_features;
   int tid;
   static uint64_t xcr0;
+  static int xsave_len;
   struct regset_info *regset;
 
   tid = lwpid_of (current_thread);
@@ -907,8 +909,6 @@ x86_linux_read_description (void)
 
   if (!use_xml)
     {
-      x86_xcr0 = X86_XSTATE_SSE_MASK;
-
       /* Don't use XML.  */
 #ifdef __x86_64__
       if (machine == EM_X86_64)
@@ -938,11 +938,13 @@ x86_linux_read_description (void)
 	  xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
 			     / sizeof (uint64_t))];
 
+	  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 = X86_XSTATE_SIZE (xcr0);
+	      regset->size = xsave_len;
 	    else if (regset->type != GENERAL_REGS)
 	      regset->size = 0;
 	}
@@ -953,7 +955,7 @@ x86_linux_read_description (void)
 		   && (xcr0 & X86_XSTATE_ALL_MASK));
 
   if (xcr0_features)
-    x86_xcr0 = xcr0;
+    i387_set_xsave_mask (xcr0, xsave_len);
 
   if (machine == EM_X86_64)
     {
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 12/15] gdbserver: Refactor the legacy region within the xsave struct
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (10 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 11/15] gdbserver: Add a function to set the XSAVE mask and size John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-08-28 16:50   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 13/15] gdbserver: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Aleksandar Paunovic

From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>

Legacy fields of the XSAVE area are already defined within fx_save
struct.  Use class inheritance to remove code duplication.

The two changed functions are called within all tests which run
gdbserver.

Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
Co-authored-by: John Baldwin <jhb@FreeBSD.org>
---
 gdbserver/i387-fp.cc | 27 ++-------------------------
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
index b8d7a912f26..a122e2d860b 100644
--- a/gdbserver/i387-fp.cc
+++ b/gdbserver/i387-fp.cc
@@ -81,29 +81,7 @@ struct i387_fxsave {
   unsigned char xmm_space[256];
 };
 
-struct i387_xsave {
-  /* All these are only sixteen bits, plus padding, except for fop (which
-     is only eleven bits), and fooff / fioff (which are 32 bits each).  */
-  unsigned short fctrl;
-  unsigned short fstat;
-  unsigned short ftag;
-  unsigned short fop;
-  unsigned int fioff;
-  unsigned short fiseg;
-  unsigned short pad1;
-  unsigned int fooff;
-  unsigned short foseg;
-  unsigned short pad12;
-
-  unsigned int mxcsr;
-  unsigned int mxcsr_mask;
-
-  /* Space for eight 80-bit FP values in 128-bit spaces.  */
-  unsigned char st_space[128];
-
-  /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
-  unsigned char xmm_space[256];
-
+struct i387_xsave : public i387_fxsave {
   unsigned char reserved1[48];
 
   /* The extended control register 0 (the XFEATURE_ENABLED_MASK
@@ -725,7 +703,6 @@ void
 i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 {
   struct i387_xsave *fp = (struct i387_xsave *) buf;
-  struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
   bool amd64 = register_size (regcache->tdesc, 0) == 8;
   int i, top;
   unsigned long val;
@@ -962,7 +939,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	{
 	  int tag;
 	  if (fp->ftag & (1 << i))
-	    tag = i387_ftag (fxp, (i + 8 - top) % 8);
+	    tag = i387_ftag (fp, (i + 8 - top) % 8);
 	  else
 	    tag = 3;
 	  val |= tag << (2 * i);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 13/15] gdbserver: Use x86_xstate_layout to parse the XSAVE extended state area.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (11 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 12/15] gdbserver: Refactor the legacy region within the xsave struct John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-08-28 18:15   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 14/15] x86: Remove X86_XSTATE_SIZE and related constants John Baldwin
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Aleksandar Paunovic

From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>

Replace the extended state area fields of i387_xsave with methods which
return an offset into the XSAVE buffer.

The two changed functions are called within all tests which runs
gdbserver.

Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
Co-authored-by: John Baldwin <jhb@FreeBSD.org>
---
 gdbserver/i387-fp.cc | 117 +++++++++++++++++++++++++------------------
 1 file changed, 69 insertions(+), 48 deletions(-)

diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
index a122e2d860b..f53a6cfc477 100644
--- a/gdbserver/i387-fp.cc
+++ b/gdbserver/i387-fp.cc
@@ -82,6 +82,8 @@ struct i387_fxsave {
 };
 
 struct i387_xsave : public i387_fxsave {
+  /* Size of i387_fxsave is 416 bytes.  */
+
   unsigned char reserved1[48];
 
   /* The extended control register 0 (the XFEATURE_ENABLED_MASK
@@ -93,34 +95,53 @@ struct i387_xsave : public i387_fxsave {
   /* The XSTATE_BV bit vector.  */
   unsigned long long xstate_bv;
 
-  unsigned char reserved3[56];
+  /* The XCOMP_BV bit vector.  */
+  unsigned long long xcomp_bv;
 
-  /* Space for eight upper 128-bit YMM values, or 16 on x86-64.  */
-  unsigned char ymmh_space[256];
+  unsigned char reserved3[48];
 
-  unsigned char reserved4[128];
+  /* Byte 576.  End of registers with fixed position in XSAVE.
+     The position of other XSAVE registers will be calculated
+     from the appropriate CPUID calls.  */
 
-  /* Space for 4 bound registers values of 128 bits.  */
-  unsigned char mpx_bnd_space[64];
+private:
+  /* Base address of XSAVE data as an unsigned char *.  Used to derive
+     pointers to XSAVE state components in the extended state
+     area.  */
+  unsigned char *xsave ()
+  { return reinterpret_cast<unsigned char *> (this); }
 
-  /* Space for 2 MPX configuration registers of 64 bits
+public:
+  /* Memory address of eight upper 128-bit YMM values, or 16 on x86-64.  */
+  unsigned char *ymmh_space ()
+  { return xsave () + xsave_layout.avx_offset; }
+
+  /* Memory address of 4 bound registers values of 128 bits.  */
+  unsigned char *bndregs_space ()
+  { return xsave () + xsave_layout.bndregs_offset; }
+
+  /* Memory address of 2 MPX configuration registers of 64 bits
      plus reserved space.  */
-  unsigned char mpx_cfg_space[16];
+  unsigned char *bndcfg_space ()
+  { return xsave () + xsave_layout.bndcfg_offset; }
 
-  unsigned char reserved5[48];
+  /* Memory address of 8 OpMask register values of 64 bits.  */
+  unsigned char *k_space ()
+  { return xsave () + xsave_layout.k_offset; }
 
-  /* Space for 8 OpMask register values of 64 bits.  */
-  unsigned char k_space[64];
+  /* Memory address of 16 256-bit zmm0-15.  */
+  unsigned char *zmmh_space ()
+  { return xsave () + xsave_layout.zmm_h_offset; }
 
-  /* Space for 16 256-bit zmm0-15.  */
-  unsigned char zmmh_low_space[512];
+  /* Memory address of 16 512-bit zmm16-31 values.  */
+  unsigned char *zmm_space ()
+  { return xsave () + xsave_layout.zmm_offset; }
 
-  /* Space for 16 512-bit zmm16-31 values.  */
-  unsigned char zmmh_high_space[1024];
-
-  /* Space for 1 32-bit PKRU register.  The HW XSTATE size for this feature is
-     actually 64 bits, but WRPKRU/RDPKRU instructions ignore upper 32 bits.  */
-  unsigned char pkru_space[8];
+  /* Memory address of 1 32-bit PKRU register.  The HW XSTATE size for this
+     feature is actually 64 bits, but WRPKRU/RDPKRU instructions ignore upper
+     32 bits.  */
+  unsigned char *pkru_space ()
+  { return xsave () + xsave_layout.pkru_offset; }
 };
 
 void
@@ -242,7 +263,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
   unsigned long long xstate_bv = 0;
   unsigned long long clear_bv = 0;
   char raw[64];
-  char *p;
+  unsigned char *p;
 
   /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
   int num_xmm_registers = amd64 ? 16 : 8;
@@ -282,40 +303,40 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
 
       if ((clear_bv & X86_XSTATE_AVX))
 	for (i = 0; i < num_xmm_registers; i++)
-	  memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
+	  memset (fp->ymmh_space () + i * 16, 0, 16);
 
       if ((clear_bv & X86_XSTATE_SSE) && (clear_bv & X86_XSTATE_AVX))
 	memset (((char *) &fp->mxcsr), 0, 4);
 
       if ((clear_bv & X86_XSTATE_BNDREGS))
 	for (i = 0; i < num_mpx_bnd_registers; i++)
-	  memset (((char *) &fp->mpx_bnd_space[0]) + i * 16, 0, 16);
+	  memset (fp->bndregs_space () + i * 16, 0, 16);
 
       if ((clear_bv & X86_XSTATE_BNDCFG))
 	for (i = 0; i < num_mpx_cfg_registers; i++)
-	  memset (((char *) &fp->mpx_cfg_space[0]) + i * 8, 0, 8);
+	  memset (fp->bndcfg_space () + i * 8, 0, 8);
 
       if ((clear_bv & X86_XSTATE_K))
 	for (i = 0; i < num_avx512_k_registers; i++)
-	  memset (((char *) &fp->k_space[0]) + i * 8, 0, 8);
+	  memset (fp->k_space () + i * 8, 0, 8);
 
       if ((clear_bv & X86_XSTATE_ZMM_H))
 	for (i = 0; i < num_avx512_zmmh_low_registers; i++)
-	  memset (((char *) &fp->zmmh_low_space[0]) + i * 32, 0, 32);
+	  memset (fp->zmmh_space () + i * 32, 0, 32);
 
       if ((clear_bv & X86_XSTATE_ZMM))
 	{
 	  for (i = 0; i < num_avx512_zmmh_high_registers; i++)
-	    memset (((char *) &fp->zmmh_high_space[0]) + 32 + i * 64, 0, 32);
+	    memset (fp->zmm_space () + 32 + i * 64, 0, 32);
 	  for (i = 0; i < num_avx512_xmm_registers; i++)
-	    memset (((char *) &fp->zmmh_high_space[0]) + i * 64, 0, 16);
+	    memset (fp->zmm_space () + i * 64, 0, 16);
 	  for (i = 0; i < num_avx512_ymmh_registers; i++)
-	    memset (((char *) &fp->zmmh_high_space[0]) + 16 + i * 64, 0, 16);
+	    memset (fp->zmm_space () + 16 + i * 64, 0, 16);
 	}
 
       if ((clear_bv & X86_XSTATE_PKRU))
 	for (i = 0; i < num_pkeys_registers; i++)
-	  memset (((char *) &fp->pkru_space[0]) + i * 4, 0, 4);
+	  memset (fp->pkru_space () + i * 4, 0, 4);
     }
 
   /* Check if any x87 registers are changed.  */
@@ -326,7 +347,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < 8; i++)
 	{
 	  collect_register (regcache, i + st0_regnum, raw);
-	  p = ((char *) &fp->st_space[0]) + i * 16;
+	  p = fp->st_space + i * 16;
 	  if (memcmp (raw, p, 10))
 	    {
 	      xstate_bv |= X86_XSTATE_X87;
@@ -343,7 +364,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_xmm_registers; i++) 
 	{
 	  collect_register (regcache, i + xmm0_regnum, raw);
-	  p = ((char *) &fp->xmm_space[0]) + i * 16;
+	  p = fp->xmm_space + i * 16;
 	  if (memcmp (raw, p, 16))
 	    {
 	      xstate_bv |= X86_XSTATE_SSE;
@@ -360,7 +381,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_xmm_registers; i++) 
 	{
 	  collect_register (regcache, i + ymm0h_regnum, raw);
-	  p = ((char *) &fp->ymmh_space[0]) + i * 16;
+	  p = fp->ymmh_space () + i * 16;
 	  if (memcmp (raw, p, 16))
 	    {
 	      xstate_bv |= X86_XSTATE_AVX;
@@ -377,7 +398,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_mpx_bnd_registers; i++)
 	{
 	  collect_register (regcache, i + bnd0r_regnum, raw);
-	  p = ((char *) &fp->mpx_bnd_space[0]) + i * 16;
+	  p = fp->bndregs_space () + i * 16;
 	  if (memcmp (raw, p, 16))
 	    {
 	      xstate_bv |= X86_XSTATE_BNDREGS;
@@ -394,7 +415,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_mpx_cfg_registers; i++)
 	{
 	  collect_register (regcache, i + bndcfg_regnum, raw);
-	  p = ((char *) &fp->mpx_cfg_space[0]) + i * 8;
+	  p = fp->bndcfg_space () + i * 8;
 	  if (memcmp (raw, p, 8))
 	    {
 	      xstate_bv |= X86_XSTATE_BNDCFG;
@@ -411,7 +432,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_avx512_k_registers; i++)
 	{
 	  collect_register (regcache, i + k0_regnum, raw);
-	  p = ((char *) &fp->k_space[0]) + i * 8;
+	  p = fp->k_space () + i * 8;
 	  if (memcmp (raw, p, 8) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_K;
@@ -428,7 +449,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_avx512_zmmh_low_registers; i++)
 	{
 	  collect_register (regcache, i + zmm0h_regnum, raw);
-	  p = ((char *) &fp->zmmh_low_space[0]) + i * 32;
+	  p = fp->zmmh_space () + i * 32;
 	  if (memcmp (raw, p, 32) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM_H;
@@ -447,7 +468,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_avx512_zmmh_high_registers; i++)
 	{
 	  collect_register (regcache, i + zmm16h_regnum, raw);
-	  p = ((char *) &fp->zmmh_high_space[0]) + 32 + i * 64;
+	  p = fp->zmm_space () + 32 + i * 64;
 	  if (memcmp (raw, p, 32) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM;
@@ -466,7 +487,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_avx512_xmm_registers; i++)
 	{
 	  collect_register (regcache, i + xmm_avx512_regnum, raw);
-	  p = ((char *) &fp->zmmh_high_space[0]) + i * 64;
+	  p = fp->zmm_space () + i * 64;
 	  if (memcmp (raw, p, 16) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM;
@@ -485,7 +506,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_avx512_ymmh_registers; i++)
 	{
 	  collect_register (regcache, i + ymmh_avx512_regnum, raw);
-	  p = ((char *) &fp->zmmh_high_space[0]) + 16 + i * 64;
+	  p = fp->zmm_space () + 16 + i * 64;
 	  if (memcmp (raw, p, 16) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM;
@@ -502,7 +523,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_pkeys_registers; i++)
 	{
 	  collect_register (regcache, i + pkru_regnum, raw);
-	  p = ((char *) &fp->pkru_space[0]) + i * 4;
+	  p = fp->pkru_space () + i * 4;
 	  if (memcmp (raw, p, 4) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_PKRU;
@@ -707,7 +728,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
   int i, top;
   unsigned long val;
   unsigned long long clear_bv;
-  gdb_byte *p;
+  unsigned char *p;
 
    /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
   int num_xmm_registers = amd64 ? 16 : 8;
@@ -768,7 +789,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
       else
 	{
-	  p = (gdb_byte *) &fp->ymmh_space[0];
+	  p = fp->ymmh_space ();
 	  for (i = 0; i < num_xmm_registers; i++)
 	    supply_register (regcache, i + ymm0h_regnum, p + i * 16);
 	}
@@ -786,7 +807,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
       else
 	{
-	  p = (gdb_byte *) &fp->mpx_bnd_space[0];
+	  p = fp->bndregs_space ();
 	  for (i = 0; i < num_mpx_bnd_registers; i++)
 	    supply_register (regcache, i + bnd0r_regnum, p + i * 16);
 	}
@@ -804,7 +825,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
       else
 	{
-	  p = (gdb_byte *) &fp->mpx_cfg_space[0];
+	  p = fp->bndcfg_space ();
 	  for (i = 0; i < num_mpx_cfg_registers; i++)
 	    supply_register (regcache, i + bndcfg_regnum, p + i * 8);
 	}
@@ -821,7 +842,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
       else
 	{
-	  p = (gdb_byte *) &fp->k_space[0];
+	  p = fp->k_space ();
 	  for (i = 0; i < num_avx512_k_registers; i++)
 	    supply_register (regcache, i + k0_regnum, p + i * 8);
 	}
@@ -838,7 +859,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
       else
 	{
-	  p = (gdb_byte *) &fp->zmmh_low_space[0];
+	  p = fp->zmmh_space ();
 	  for (i = 0; i < num_avx512_zmmh_low_registers; i++)
 	    supply_register (regcache, i + zmm0h_regnum, p + i * 32);
 	}
@@ -867,7 +888,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
       else
 	{
-	  p = (gdb_byte *) &fp->zmmh_high_space[0];
+	  p = fp->zmm_space ();
 	  for (i = 0; i < num_avx512_zmmh_high_registers; i++)
 	    supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
 	  for (i = 0; i < num_avx512_ymmh_registers; i++)
@@ -888,7 +909,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
       else
 	{
-	  p = (gdb_byte *) &fp->pkru_space[0];
+	  p = fp->pkru_space ();
 	  for (i = 0; i < num_pkeys_registers; i++)
 	    supply_register (regcache, i + pkru_regnum, p + i * 4);
 	}
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 14/15] x86: Remove X86_XSTATE_SIZE and related constants.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (12 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 13/15] gdbserver: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-08-28 20:38   ` Simon Marchi
  2023-07-14 15:51 ` [PATCH v6 15/15] gdbserver: Simplify handling of ZMM registers John Baldwin
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

---
 gdbsupport/x86-xstate.h | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
index 27fc0bd12f2..40963bda55b 100644
--- a/gdbsupport/x86-xstate.h
+++ b/gdbsupport/x86-xstate.h
@@ -99,11 +99,6 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
 
 #define X86_XSTATE_SSE_SIZE	576
 #define X86_XSTATE_AVX_SIZE	832
-#define X86_XSTATE_BNDREGS_SIZE	1024
-#define X86_XSTATE_BNDCFG_SIZE	1088
-#define X86_XSTATE_AVX512_SIZE	2688
-#define X86_XSTATE_PKRU_SIZE	2696
-#define X86_XSTATE_MAX_SIZE	2696
 
 
 /* In case one of the MPX XCR0 bits is set we consider we have MPX.  */
@@ -112,13 +107,6 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
 #define HAS_AVX512(XCR0) (((XCR0) & X86_XSTATE_AVX512) != 0)
 #define HAS_PKRU(XCR0) (((XCR0) & X86_XSTATE_PKRU) != 0)
 
-/* Get I386 XSAVE extended state size.  */
-#define X86_XSTATE_SIZE(XCR0) \
-    (HAS_PKRU (XCR0) ? X86_XSTATE_PKRU_SIZE : \
-     (HAS_AVX512 (XCR0) ? X86_XSTATE_AVX512_SIZE : \
-      (HAS_MPX (XCR0) ? X86_XSTATE_BNDCFG_SIZE : \
-       (HAS_AVX (XCR0) ? X86_XSTATE_AVX_SIZE : X86_XSTATE_SSE_SIZE))))
-
 /* Initial value for fctrl register, as defined in the X86 manual, and
    confirmed in the (Linux) kernel source.  When the x87 floating point
    feature is not enabled in an inferior we use this as the value of the
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6 15/15] gdbserver: Simplify handling of ZMM registers.
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (13 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 14/15] x86: Remove X86_XSTATE_SIZE and related constants John Baldwin
@ 2023-07-14 15:51 ` John Baldwin
  2023-08-28 20:57   ` Simon Marchi
  2023-07-14 15:58 ` [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
  2023-07-25 17:17 ` Keith Seitz
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:51 UTC (permalink / raw)
  To: gdb-patches

- Reuse num_xmm_registers directly for the count of ZMM0-15 registers
  as is already done for the YMM registers for AVX rather than using
  a new variable that is always the same.

- Replace 3 identical variables for the count of upper ZMM16-31
  registers with a single variable.  Make use of this to merge
  various loops working on the ZMM XSAVE region so that all of the
  handling for the various sub-registers in this region are always
  handled in a single loop.

- While here, fix some bugs in i387_cache_to_xsave on where if
  X86_XSTATE_ZMM was set on i386 (e.g. a 32-bit process on a 64-bit
  kernel), the -1 register nums would wrap around and store the
  value of GPRs in the XSAVE area.  This should be harmless, but
  is definitely odd.  Instead, check num_zmm_high_registers directly
  when checking X86_XSTATE_ZMM and skip the ZMM region handling
  entirely if the register count is 0.
---
 gdbserver/i387-fp.cc | 132 +++++++++++++++----------------------------
 1 file changed, 46 insertions(+), 86 deletions(-)

diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
index f53a6cfc477..91d3a0b8ca3 100644
--- a/gdbserver/i387-fp.cc
+++ b/gdbserver/i387-fp.cc
@@ -267,12 +267,8 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
 
   /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
   int num_xmm_registers = amd64 ? 16 : 8;
-  /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm.  */
-  int num_avx512_zmmh_low_registers = num_xmm_registers;
-  /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
-  int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
-  int num_avx512_ymmh_registers = amd64 ? 16 : 0;
-  int num_avx512_xmm_registers = amd64 ? 16 : 0;
+  /* AVX512 adds 16 extra ZMM regs in Amd64 mode, but none in I386 mode.*/
+  int num_zmm_high_registers = amd64 ? 16 : 0;
 
   /* The supported bits in `xstat_bv' are 8 bytes.  Clear part in
      vector registers if its bit in xstat_bv is zero.  */
@@ -321,18 +317,12 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
 	  memset (fp->k_space () + i * 8, 0, 8);
 
       if ((clear_bv & X86_XSTATE_ZMM_H))
-	for (i = 0; i < num_avx512_zmmh_low_registers; i++)
+	for (i = 0; i < num_xmm_registers; i++)
 	  memset (fp->zmmh_space () + i * 32, 0, 32);
 
       if ((clear_bv & X86_XSTATE_ZMM))
-	{
-	  for (i = 0; i < num_avx512_zmmh_high_registers; i++)
-	    memset (fp->zmm_space () + 32 + i * 64, 0, 32);
-	  for (i = 0; i < num_avx512_xmm_registers; i++)
-	    memset (fp->zmm_space () + i * 64, 0, 16);
-	  for (i = 0; i < num_avx512_ymmh_registers; i++)
-	    memset (fp->zmm_space () + 16 + i * 64, 0, 16);
-	}
+	for (i = 0; i < num_zmm_high_registers; i++)
+	  memset (fp->zmm_space () + i * 64, 0, 64);
 
       if ((clear_bv & X86_XSTATE_PKRU))
 	for (i = 0; i < num_pkeys_registers; i++)
@@ -446,7 +436,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
     {
       int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
 
-      for (i = 0; i < num_avx512_zmmh_low_registers; i++)
+      for (i = 0; i < num_xmm_registers; i++)
 	{
 	  collect_register (regcache, i + zmm0h_regnum, raw);
 	  p = fp->zmmh_space () + i * 32;
@@ -458,55 +448,35 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
 	}
     }
 
-  /* Check if any of ZMM16H-ZMM31H registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM))
+  /* Check if any of ZMM16-ZMM31 registers are changed.  */
+  if ((x86_xcr0 & X86_XSTATE_ZMM) && num_zmm_high_registers != 0)
     {
-      int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
-			   ? -1
-			   : find_regno (regcache->tdesc, "zmm16h"));
+      int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
+      int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
+      int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
 
-      for (i = 0; i < num_avx512_zmmh_high_registers; i++)
+      for (i = 0; i < num_zmm_high_registers; i++)
 	{
-	  collect_register (regcache, i + zmm16h_regnum, raw);
-	  p = fp->zmm_space () + 32 + i * 64;
-	  if (memcmp (raw, p, 32) != 0)
-	    {
-	      xstate_bv |= X86_XSTATE_ZMM;
-	      memcpy (p, raw, 32);
-	    }
-	}
-    }
-
-  /* Check if any XMM_AVX512 registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM))
-    {
-      int xmm_avx512_regnum = (num_avx512_xmm_registers == 0
-			       ? -1
-			       : find_regno (regcache->tdesc, "xmm16"));
-
-      for (i = 0; i < num_avx512_xmm_registers; i++)
-	{
-	  collect_register (regcache, i + xmm_avx512_regnum, raw);
 	  p = fp->zmm_space () + i * 64;
-	  if (memcmp (raw, p, 16) != 0)
+
+	  /* ZMMH sub-register.  */
+	  collect_register (regcache, i + zmm16h_regnum, raw);
+	  if (memcmp (raw, p + 32, 32) != 0)
+	    {
+	      xstate_bv |= X86_XSTATE_ZMM;
+	      memcpy (p, raw, 32);
+	    }
+
+	  /* YMMH sub-register.  */
+	  collect_register (regcache, i + ymm16h_regnum, raw);
+	  if (memcmp (raw, p + 16, 16) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM;
 	      memcpy (p, raw, 16);
 	    }
-	}
-    }
 
-  /* Check if any YMMH_AVX512 registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM))
-    {
-      int ymmh_avx512_regnum = (num_avx512_ymmh_registers == 0
-				? -1
-				: find_regno (regcache->tdesc, "ymm16h"));
-
-      for (i = 0; i < num_avx512_ymmh_registers; i++)
-	{
-	  collect_register (regcache, i + ymmh_avx512_regnum, raw);
-	  p = fp->zmm_space () + 16 + i * 64;
+	  /* XMM sub-register.  */
+	  collect_register (regcache, i + xmm16_regnum, raw);
 	  if (memcmp (raw, p, 16) != 0)
 	    {
 	      xstate_bv |= X86_XSTATE_ZMM;
@@ -732,12 +702,8 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 
    /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
   int num_xmm_registers = amd64 ? 16 : 8;
-  /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm.  */
-  int num_avx512_zmmh_low_registers = num_xmm_registers;
-  /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
-  int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
-  int num_avx512_ymmh_registers = amd64 ? 16 : 0;
-  int num_avx512_xmm_registers = amd64 ? 16 : 0;
+  /* AVX512 adds 16 extra ZMM regs in Amd64 mode, but none in I386 mode.*/
+  int num_zmm_high_registers = amd64 ? 16 : 0;
 
   /* The supported bits in `xstat_bv' are 8 bytes.  Clear part in
      vector registers if its bit in xstat_bv is zero.  */
@@ -854,47 +820,41 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 
       if ((clear_bv & X86_XSTATE_ZMM_H) != 0)
 	{
-	  for (i = 0; i < num_avx512_zmmh_low_registers; i++)
+	  for (i = 0; i < num_xmm_registers; i++)
 	    supply_register_zeroed (regcache, i + zmm0h_regnum);
 	}
       else
 	{
 	  p = fp->zmmh_space ();
-	  for (i = 0; i < num_avx512_zmmh_low_registers; i++)
+	  for (i = 0; i < num_xmm_registers; i++)
 	    supply_register (regcache, i + zmm0h_regnum, p + i * 32);
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_ZMM) != 0)
+  if ((x86_xcr0 & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0)
     {
-      int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
-			   ? -1
-			   : find_regno (regcache->tdesc, "zmm16h"));
-      int ymm16h_regnum = (num_avx512_ymmh_registers == 0
-			   ? -1
-			   : find_regno (regcache->tdesc, "ymm16h"));
-      int xmm16_regnum = (num_avx512_xmm_registers == 0
-			  ? -1
-			  : find_regno (regcache->tdesc, "xmm16"));
+      int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
+      int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
+      int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
 
       if ((clear_bv & X86_XSTATE_ZMM) != 0)
 	{
-	  for (i = 0; i < num_avx512_zmmh_high_registers; i++)
-	    supply_register_zeroed (regcache, i + zmm16h_regnum);
-	  for (i = 0; i < num_avx512_ymmh_registers; i++)
-	    supply_register_zeroed (regcache, i + ymm16h_regnum);
-	  for (i = 0; i < num_avx512_xmm_registers; i++)
-	    supply_register_zeroed (regcache, i + xmm16_regnum);
+	  for (i = 0; i < num_zmm_high_registers; i++)
+	    {
+	      supply_register_zeroed (regcache, i + zmm16h_regnum);
+	      supply_register_zeroed (regcache, i + ymm16h_regnum);
+	      supply_register_zeroed (regcache, i + xmm16_regnum);
+	    }
 	}
       else
 	{
 	  p = fp->zmm_space ();
-	  for (i = 0; i < num_avx512_zmmh_high_registers; i++)
-	    supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
-	  for (i = 0; i < num_avx512_ymmh_registers; i++)
-	    supply_register (regcache, i + ymm16h_regnum, p + 16 + i * 64);
-	  for (i = 0; i < num_avx512_xmm_registers; i++)
-	    supply_register (regcache, i + xmm16_regnum, p + i * 64);
+	  for (i = 0; i < num_zmm_high_registers; i++)
+	    {
+	      supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
+	      supply_register (regcache, i + ymm16h_regnum, p + 16 + i * 64);
+	      supply_register (regcache, i + xmm16_regnum, p + i * 64);
+	    }
 	}
     }
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (14 preceding siblings ...)
  2023-07-14 15:51 ` [PATCH v6 15/15] gdbserver: Simplify handling of ZMM registers John Baldwin
@ 2023-07-14 15:58 ` John Baldwin
  2023-07-26  8:31   ` Willgerodt, Felix
  2023-07-25 17:17 ` Keith Seitz
  16 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-14 15:58 UTC (permalink / raw)
  To: gdb-patches; +Cc: Joel Brobecker, George, Jini Susan

On 7/14/23 8:51 AM, John Baldwin wrote:
> Changes since V5:
> 
> - A few fixes not tied to the new layout handling have been merged to
>    master.
> 
> - Reworded the comment describing i386_*_core_read_xsave_info in patches
>    6 and 8.
> 
> Aleksandar Paunovic (2):
>    gdbserver: Refactor the legacy region within the xsave struct
>    gdbserver: Use x86_xstate_layout to parse the XSAVE extended state
>      area.
> 
> John Baldwin (13):
>    x86: Add an x86_xsave_layout structure to handle variable XSAVE
>      layouts.
>    gdb: Store an x86_xsave_layout in i386_gdbarch_tdep.
>    core: Support fetching x86 XSAVE layout from architectures.
>    nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count.
>    x86 nat: Add helper functions to save the XSAVE layout for the host.
>    gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
>    gdb: Support XSAVE layouts for the current host in the FreeBSD x86
>      targets.
>    gdb: Update x86 Linux architectures to support XSAVE layouts.
>    gdb: Support XSAVE layouts for the current host in the Linux x86
>      targets.
>    gdb: Use x86_xstate_layout to parse the XSAVE extended state area.
>    gdbserver: Add a function to set the XSAVE mask and size.
>    x86: Remove X86_XSTATE_SIZE and related constants.
>    gdbserver: Simplify handling of ZMM registers.

I would like to get this series into GDB 14 if possible.  Without it one
cannot examine certain XSAVE registers (e.g. YMM for AVX) in core dumps
generated on modern AMD CPUs on both Linux and FreeBSD.

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
                   ` (15 preceding siblings ...)
  2023-07-14 15:58 ` [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
@ 2023-07-25 17:17 ` Keith Seitz
  2023-07-25 18:15   ` John Baldwin
  16 siblings, 1 reply; 58+ messages in thread
From: Keith Seitz @ 2023-07-25 17:17 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

Hi,

On 7/14/23 08:51, John Baldwin wrote:
> Changes since V5:
> 
> - A few fixes not tied to the new layout handling have been merged to
>    master.
> 
> - Reworded the comment describing i386_*_core_read_xsave_info in patches
>    6 and 8.
> 

I am sorry I am late to the review here, but I've been testing Sapphire
Rapids this past week (and its expanded register save area), and thought
I would dig into this a bit, testing it on random x86 systems in our (internal)
test farm.
  
The (unsurprising) good news is that on RHEL9, this series does not adversely
affect regression testing results on ppc64le, aarch64, or s390x. It also
greatly improves results on Sapphire Rapids CPUs (at least on the native
unix target).

However, I've run into some pretty consistent problems which I have not yet begun to
investigate (likely all the same bug).

With either a Raptor Lake CPU ("13th Gen Intel(R) Core(TM) i7-13700") or Sapphire
Rapids ("Intel(R) Xeon(R) Gold 5418Y"), I can get gdb to consistently segfault in
memcpy in several tests using gdbserver w/-m32:

$ make check RUNTESTFLAGS="--target_board native-gdbserver/-m32" TESTS=gdb.base/auxv.exp
[snip]
		=== gdb Summary ===

# of expected passes		6
# of unexpected failures	1
# of unresolved testcases	5
# of unsupported tests		3

 From gdb.log:

(gdb) PASS: gdb.base/auxv.exp: info auxv on live process
gcore /root/test-fsf-master/gdb/build-x86_64-redhat-linux-gnu/gdb/testsuite/outputs/gdb.base/auxv/auxv.gcore


Fatal signal: Segmentation fault
----- Backtrace -----
0x55ef54b9acda gdb_internal_backtrace_1
         ../../gdb/bt-utils.c:122
0x55ef54b9acda _Z22gdb_internal_backtracev
         ../../gdb/bt-utils.c:168
0x55ef54b9acda _Z22gdb_internal_backtracev
         ../../gdb/bt-utils.c:154
0x55ef54cc086e handle_fatal_signal
         ../../gdb/event-top.c:889
0x55ef54cc0a78 handle_sigsegv
         ../../gdb/event-top.c:962
0x7fd237654dcf ???
0x55ef54d4e9bf memcpy
         /usr/include/bits/string_fortified.h:29
0x55ef54d4e9bf _Z18i387_collect_xsavePK8regcacheiPvi
         ../../gdb/i387-tdep.c:1543
0x55ef54d062c8 gcore_elf_collect_regset_section_cb
         ../../gdb/gcore-elf.c:85
0x55ef54d057ac gcore_elf_collect_thread_registers
         ../../gdb/gcore-elf.c:121
0x55ef54d057ac _Z37gcore_elf_build_thread_register_notesP7gdbarchP11thread_info10gdb_signalP3bfdPSt10unique_ptrIcN3gdb13xfree_deleterIcEEEPi
         ../../gdb/gcore-elf.c:135
0x55ef54db378f linux_corefile_thread
         ../../gdb/linux-tdep.c:1846
0x55ef54db3aec linux_make_corefile_notes
         ../../gdb/linux-tdep.c:2102
0x55ef54d06777 _Z27gdbarch_make_corefile_notesP7gdbarchP3bfdPi
         ../../gdb/gdbarch.c:3743
0x55ef54d06777 write_gcore_file_1
         ../../gdb/gcore.c:82
0x55ef54d070f7 _Z16write_gcore_fileP3bfd
         ../../gdb/gcore.c:119
0x55ef54d070f7 gcore_command
         ../../gdb/gcore.c:157
0x55ef54be0fe4 _Z8cmd_funcP16cmd_list_elementPKci
         ../../gdb/cli/cli-decode.c:2735
0x55ef54fca4b0 _Z15execute_commandPKci
         ../../gdb/top.c:574
0x55ef54cc91b7 _Z15command_handlerPKc
         ../../gdb/event-top.c:552
0x55ef54cc9263 _Z20command_line_handlerOSt10unique_ptrIcN3gdb13xfree_deleterIcEEE
         ../../gdb/event-top.c:788
0x55ef54cc048c gdb_rl_callback_handler
         ../../gdb/event-top.c:259
0x7fd2384c65bd ???
0x55ef54cc6a1a gdb_rl_callback_read_char_wrapper_noexcept
         ../../gdb/event-top.c:195
0x55ef54cc6c03 gdb_rl_callback_read_char_wrapper
         ../../gdb/event-top.c:234
0x55ef54fedc6f stdin_event_handler
         ../../gdb/ui.c:155
0x55ef551c5f2d gdb_wait_for_event
         ../gdbsupport/../../gdbsupport/event-loop.cc:694
0x55ef551c5f2d gdb_wait_for_event
         ../gdbsupport/../../gdbsupport/event-loop.cc:585
0x55ef5522c227 _Z16gdb_do_one_eventi.constprop.0
         ../gdbsupport/../../gdbsupport/event-loop.cc:264
0x55ef54dc8634 start_event_loop
         ../../gdb/main.c:412
0x55ef54dc8634 captured_command_loop
         ../../gdb/main.c:476
0x55ef54aaee2c captured_main
         ../../gdb/main.c:1320
0x55ef54aaee2c _Z8gdb_mainP18captured_main_args
         ../../gdb/main.c:1339
0x55ef54aaee2c main
         ../../gdb/gdb.c:32
---------------------
A fatal error internal to GDB has been detected, further
debugging is not possible.  GDB will now terminate.

This is a bug, please report it.  For instructions, see:
<https://www.gnu.org/software/gdb/bugs/>.

ERROR: GDB process no longer exists

A complete list of affected tests:

gdb.base/auxv.exp
gdb.base/coredump-filter.exp
gdb.base/corefile2.exp
gdb.base/gcore-tls-pie.exp
gdb.base/gcore.exp
gdb.base/info-proc.exp
gdb.base/patch.exp
gdb.base/print-symbol-loading.exp
gdb.base/siginfo-obj.exp
gdb.base/siginfo-thread.exp
gdb.base/solib-search.exp
gdb.base/vdso-warning.exp
gdb.btrace/gcore.exp
gdb.python/py-strfns.exp
gdb.reverse/break-precsave.exp
gdb.reverse/consecutive-precsave.exp
gdb.reverse/finish-precsave.exp
gdb.reverse/i386-precsave.exp
gdb.reverse/machinestate-precsave.exp
gdb.reverse/sigall-precsave.exp
gdb.reverse/solib-precsave.exp
gdb.reverse/step-precsave.exp
gdb.reverse/until-precsave.exp
gdb.threads/tls-core.exp same

The unix/-m32 target does not exhibit these problems. Just the
gdbserver targets (native-gdbserver, native-extended-gdbserver).

On my personal machine, a Comet Lake, all of these tests work/pass.

Keith


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-25 17:17 ` Keith Seitz
@ 2023-07-25 18:15   ` John Baldwin
  2023-07-25 18:43     ` Keith Seitz
  0 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-25 18:15 UTC (permalink / raw)
  To: Keith Seitz, gdb-patches

On 7/25/23 10:17 AM, Keith Seitz wrote:
> Hi,
> 
> On 7/14/23 08:51, John Baldwin wrote:
>> Changes since V5:
>>
>> - A few fixes not tied to the new layout handling have been merged to
>>     master.
>>
>> - Reworded the comment describing i386_*_core_read_xsave_info in patches
>>     6 and 8.
>>
> 
> I am sorry I am late to the review here, but I've been testing Sapphire
> Rapids this past week (and its expanded register save area), and thought
> I would dig into this a bit, testing it on random x86 systems in our (internal)
> test farm.
>    
> The (unsurprising) good news is that on RHEL9, this series does not adversely
> affect regression testing results on ppc64le, aarch64, or s390x. It also
> greatly improves results on Sapphire Rapids CPUs (at least on the native
> unix target).
> 
> However, I've run into some pretty consistent problems which I have not yet begun to
> investigate (likely all the same bug).
> 
> With either a Raptor Lake CPU ("13th Gen Intel(R) Core(TM) i7-13700") or Sapphire
> Rapids ("Intel(R) Xeon(R) Gold 5418Y"), I can get gdb to consistently segfault in
> memcpy in several tests using gdbserver w/-m32:
> 
> $ make check RUNTESTFLAGS="--target_board native-gdbserver/-m32" TESTS=gdb.base/auxv.exp
> [snip]
> 		=== gdb Summary ===
> 
> # of expected passes		6
> # of unexpected failures	1
> # of unresolved testcases	5
> # of unsupported tests		3
> 
>   From gdb.log:
> 
> (gdb) PASS: gdb.base/auxv.exp: info auxv on live process
> gcore /root/test-fsf-master/gdb/build-x86_64-redhat-linux-gnu/gdb/testsuite/outputs/gdb.base/auxv/auxv.gcore
> 
> 
> Fatal signal: Segmentation fault
> ----- Backtrace -----
> 0x55ef54b9acda gdb_internal_backtrace_1
>           ../../gdb/bt-utils.c:122
> 0x55ef54b9acda _Z22gdb_internal_backtracev
>           ../../gdb/bt-utils.c:168
> 0x55ef54b9acda _Z22gdb_internal_backtracev
>           ../../gdb/bt-utils.c:154
> 0x55ef54cc086e handle_fatal_signal
>           ../../gdb/event-top.c:889
> 0x55ef54cc0a78 handle_sigsegv
>           ../../gdb/event-top.c:962
> 0x7fd237654dcf ???
> 0x55ef54d4e9bf memcpy
>           /usr/include/bits/string_fortified.h:29
> 0x55ef54d4e9bf _Z18i387_collect_xsavePK8regcacheiPvi
>           ../../gdb/i387-tdep.c:1543

Can you confirm where this is in your patched copy?  For me this line is here:

   if (gcore)
     {
       /* Clear XSAVE extended state.  */
       memset (regs, 0, tdep->xsave_layout.sizeof_xsave);

       /* Update XCR0 and `xstate_bv' with XCR0 for gcore.  */
       if (tdep->xsave_xcr0_offset != -1)
>>>	memcpy (regs + tdep->xsave_xcr0_offset, &tdep->xcr0, 8);
       memcpy (XSAVE_XSTATE_BV_ADDR (regs), &tdep->xcr0, 8);
     }

If you have a core handy, could you provide the output of 'p tdep->xsave_layout'
and 'p tdep->xsave_xcr0_offset'?

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-25 18:15   ` John Baldwin
@ 2023-07-25 18:43     ` Keith Seitz
  2023-07-25 18:59       ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Keith Seitz @ 2023-07-25 18:43 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/25/23 11:15, John Baldwin wrote:
> On 7/25/23 10:17 AM, Keith Seitz wrote:
>> On 7/14/23 08:51, John Baldwin wrote:
>> 0x55ef54d4e9bf memcpy
>>           /usr/include/bits/string_fortified.h:29
>> 0x55ef54d4e9bf _Z18i387_collect_xsavePK8regcacheiPvi
>>           ../../gdb/i387-tdep.c:1543
> 
> Can you confirm where this is in your patched copy?  For me this line is here:
> 
>    if (gcore)
>      {
>        /* Clear XSAVE extended state.  */
>        memset (regs, 0, tdep->xsave_layout.sizeof_xsave);
> 
>        /* Update XCR0 and `xstate_bv' with XCR0 for gcore.  */
>        if (tdep->xsave_xcr0_offset != -1)
>>>>     memcpy (regs + tdep->xsave_xcr0_offset, &tdep->xcr0, 8);
>        memcpy (XSAVE_XSTATE_BV_ADDR (regs), &tdep->xcr0, 8);
>      }

Yes, that's the problem spot.

> If you have a core handy, could you provide the output of 'p tdep->xsave_layout'
> and 'p tdep->xsave_xcr0_offset'?
> 

I do have a corefile:

(gdb) up
#6  i387_collect_xsave (regcache=0x5568a96b1ab0, regnum=-1, xsave=0x0, gcore=1)
     at ../../gdb/i387-tdep.c:1543
1543		memcpy (regs + tdep->xsave_xcr0_offset, &tdep->xcr0, 8);
(gdb) p tdep->xsave_layout
$1 = {sizeof_xsave = 0, avx_offset = 0, bndregs_offset = 0, bndcfg_offset = 0,
   k_offset = 0, zmm_h_offset = 0, zmm_offset = 0, pkru_offset = 0}
(gdb) p tdep->xsave_xcr0_offset
$2 = 464

If there's anything I can do to help, please do not hesitate to ask!

Keith


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-25 18:43     ` Keith Seitz
@ 2023-07-25 18:59       ` John Baldwin
  2023-07-25 20:42         ` Keith Seitz
  0 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-25 18:59 UTC (permalink / raw)
  To: Keith Seitz, gdb-patches

On 7/25/23 11:43 AM, Keith Seitz wrote:
> On 7/25/23 11:15, John Baldwin wrote:
>> On 7/25/23 10:17 AM, Keith Seitz wrote:
>>> On 7/14/23 08:51, John Baldwin wrote:
>>> 0x55ef54d4e9bf memcpy
>>>            /usr/include/bits/string_fortified.h:29
>>> 0x55ef54d4e9bf _Z18i387_collect_xsavePK8regcacheiPvi
>>>            ../../gdb/i387-tdep.c:1543
>>
>> Can you confirm where this is in your patched copy?  For me this line is here:
>>
>>     if (gcore)
>>       {
>>         /* Clear XSAVE extended state.  */
>>         memset (regs, 0, tdep->xsave_layout.sizeof_xsave);
>>
>>         /* Update XCR0 and `xstate_bv' with XCR0 for gcore.  */
>>         if (tdep->xsave_xcr0_offset != -1)
>>>>>      memcpy (regs + tdep->xsave_xcr0_offset, &tdep->xcr0, 8);
>>         memcpy (XSAVE_XSTATE_BV_ADDR (regs), &tdep->xcr0, 8);
>>       }
> 
> Yes, that's the problem spot.
> 
>> If you have a core handy, could you provide the output of 'p tdep->xsave_layout'
>> and 'p tdep->xsave_xcr0_offset'?
>>
> 
> I do have a corefile:
> 
> (gdb) up
> #6  i387_collect_xsave (regcache=0x5568a96b1ab0, regnum=-1, xsave=0x0, gcore=1)
>       at ../../gdb/i387-tdep.c:1543
> 1543		memcpy (regs + tdep->xsave_xcr0_offset, &tdep->xcr0, 8);
> (gdb) p tdep->xsave_layout
> $1 = {sizeof_xsave = 0, avx_offset = 0, bndregs_offset = 0, bndcfg_offset = 0,
>     k_offset = 0, zmm_h_offset = 0, zmm_offset = 0, pkru_offset = 0}
> (gdb) p tdep->xsave_xcr0_offset
> $2 = 464
> 
> If there's anything I can do to help, please do not hesitate to ask!

Hmm, I would not expect to have an empty layout (xsave_layout.sizeof_xsave == 0)
and then calling collect_xsave.  We only call collect_xsave in i386_linux_tdep.c
if tdep->xcr0 indicates AVX is present.  Possibly we should only call it if
tdep->xsave_layout.sizeof_xsave != 0 instead (that is what I think I did on the
FreeBSD arches).  That said, the inconsistency in tdep->xcr0 vs xsave_layout
could be problematic elsewhere so I'd rather root it out.  Can you please run
a failing test with this local patch:

diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index d5423681802..dab3428c8e6 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8383,6 +8383,8 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
        if (!feature_sse)
  	return 0;
  
+      gdb_assert(tdep->xsave_layout.sizeof_xsave != 0);
+
        if (!feature_avx512)
  	tdep->xcr0 = X86_XSTATE_AVX_MASK;
  
@@ -8768,12 +8770,12 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
    info.tdesc_data = tdesc_data.get ();
    gdbarch_init_osabi (info, gdbarch);
  
+  tdep->xsave_layout = xsave_layout;
    if (!i386_validate_tdesc_p (tdep, tdesc_data.get ()))
      {
        gdbarch_free (gdbarch);
        return NULL;
      }
-  tdep->xsave_layout = xsave_layout;
  
    num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);

Hopefully it triggers the assertion, and then what will be useful is to see what
features the tdesc contains ('info locals' would cover that if they aren't all
optimized out).

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-25 18:59       ` John Baldwin
@ 2023-07-25 20:42         ` Keith Seitz
  2023-07-25 22:05           ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Keith Seitz @ 2023-07-25 20:42 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/25/23 11:59, John Baldwin wrote:
> 
> Hopefully it triggers the assertion, and then what will be useful is to see what
> features the tdesc contains ('info locals' would cover that if they aren't all
> optimized out).

Yes, that assertion does trigger (on all -m32 targets).

 From the native-gdbserver/-m32 case at the assertion (I have a debug build):

(top-gdb) info locals
tdesc = 0x197b410
feature_core = 0x197d5a0
feature_sse = 0x1987200
feature_avx = 0x1989db0
feature_mpx = 0x0
feature_avx512 = 0x198a310
feature_pkeys = 0x198aec0
feature_segments = 0x0
i = 0
num_regs = 32767
valid_p = 1
__func__ = "i386_validate_tdesc_p"
(top-gdb) p *tdep
$2 = {<gdbarch_tdep_base> = {
     _vptr.gdbarch_tdep_base = 0xf5df38 <vtable for i386_gdbarch_tdep+16>},
   gregset_reg_offset = 0x159fb20 <i386_linux_gregset_reg_offset>,
   gregset_num_regs = 73, sizeof_gregset = 68, sizeof_fpregset = 108,
   st0_regnum = 16, num_mmx_regs = 8, mm0_regnum = 0, num_ymm_regs = 0,
   ymm0_regnum = 0, num_k_regs = 0, k0_regnum = 55, num_zmm_regs = 8,
   zmm0_regnum = 0, num_byte_regs = 8, al_regnum = 0, num_word_regs = 8,
   ax_regnum = 0, num_dword_regs = 0, eax_regnum = 0, num_core_regs = 32,
   num_xmm_regs = 8, num_xmm_avx512_regs = 0, xmm16_regnum = -1,
   num_ymm_avx512_regs = 0, ymm16_regnum = 0, xcr0 = 231,
   xsave_xcr0_offset = 464, xsave_layout = {sizeof_xsave = 0, avx_offset = 0,
     bndregs_offset = 0, bndcfg_offset = 0, k_offset = 0, zmm_h_offset = 0,
     zmm_offset = 0, pkru_offset = 0},
   register_names = 0xf5a6a0 <i386_register_names>, ymm0h_regnum = -1,
   ymmh_register_names = 0x0, ymm16h_regnum = -1, ymm16h_register_names = 0x0,
   bnd0r_regnum = -1, bnd0_regnum = 0, bndcfgu_regnum = -1,
   mpx_register_names = 0x0, zmm0h_regnum = 63,
   k_register_names = 0xf5a900 <i386_k_names>,
   zmmh_register_names = 0xf5a8a0 <i386_zmmh_names>,
   xmm_avx512_register_names = 0x0, ymm_avx512_register_names = 0x0,
   num_pkeys_regs = 0, pkru_regnum = -1, pkeys_register_names = 0x0,
   fsbase_regnum = -1, tdesc = 0x197b410, register_reggroup_p = 0x7a9578
      <i386_linux_register_reggroup_p(gdbarch*, int, reggroup const*)>,
   jb_pc_offset = 20, struct_return = pcc_struct_return, sigtramp_start = 0x0,
   sigtramp_end = 0x0,
   sigtramp_p = 0x7a99ae <i386_linux_sigtramp_p(frame_info_ptr)>,
   sigcontext_addr = 0x7a9c52 <i386_linux_sigcontext_addr(frame_info_ptr)>,
   sc_reg_offset = 0x159fc60 <i386_linux_sc_reg_offset>, sc_num_regs = 16,
   sc_pc_offset = -1, sc_sp_offset = -1, i386_mmx_type = 0x0,
   i386_ymm_type = 0x0, i386_zmm_type = 0x0, i387_ext_type = 0x0,
   i386_bnd_type = 0x0, record_regmap = 0xf5d5a0 <i386_record_regmap>,
   i386_intx80_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>,
   i386_sysenter_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>,
   i386_syscall_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>, fpregset = 0xf5b5c0 <i386_fpregset>}

Keith


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-25 20:42         ` Keith Seitz
@ 2023-07-25 22:05           ` John Baldwin
  2023-07-26 22:31             ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-25 22:05 UTC (permalink / raw)
  To: Keith Seitz, gdb-patches

On 7/25/23 1:42 PM, Keith Seitz wrote:
> On 7/25/23 11:59, John Baldwin wrote:
>>
>> Hopefully it triggers the assertion, and then what will be useful is to see what
>> features the tdesc contains ('info locals' would cover that if they aren't all
>> optimized out).
> 
> Yes, that assertion does trigger (on all -m32 targets).
> 
>   From the native-gdbserver/-m32 case at the assertion (I have a debug build):
> 
> (top-gdb) info locals
> tdesc = 0x197b410
> feature_core = 0x197d5a0
> feature_sse = 0x1987200
> feature_avx = 0x1989db0
> feature_mpx = 0x0
> feature_avx512 = 0x198a310
> feature_pkeys = 0x198aec0
> feature_segments = 0x0
> i = 0
> num_regs = 32767
> valid_p = 1
> __func__ = "i386_validate_tdesc_p"
> (top-gdb) p *tdep
> $2 = {<gdbarch_tdep_base> = {
>       _vptr.gdbarch_tdep_base = 0xf5df38 <vtable for i386_gdbarch_tdep+16>},
>     gregset_reg_offset = 0x159fb20 <i386_linux_gregset_reg_offset>,
>     gregset_num_regs = 73, sizeof_gregset = 68, sizeof_fpregset = 108,
>     st0_regnum = 16, num_mmx_regs = 8, mm0_regnum = 0, num_ymm_regs = 0,
>     ymm0_regnum = 0, num_k_regs = 0, k0_regnum = 55, num_zmm_regs = 8,
>     zmm0_regnum = 0, num_byte_regs = 8, al_regnum = 0, num_word_regs = 8,
>     ax_regnum = 0, num_dword_regs = 0, eax_regnum = 0, num_core_regs = 32,
>     num_xmm_regs = 8, num_xmm_avx512_regs = 0, xmm16_regnum = -1,
>     num_ymm_avx512_regs = 0, ymm16_regnum = 0, xcr0 = 231,
>     xsave_xcr0_offset = 464, xsave_layout = {sizeof_xsave = 0, avx_offset = 0,
>       bndregs_offset = 0, bndcfg_offset = 0, k_offset = 0, zmm_h_offset = 0,
>       zmm_offset = 0, pkru_offset = 0},
>     register_names = 0xf5a6a0 <i386_register_names>, ymm0h_regnum = -1,
>     ymmh_register_names = 0x0, ymm16h_regnum = -1, ymm16h_register_names = 0x0,
>     bnd0r_regnum = -1, bnd0_regnum = 0, bndcfgu_regnum = -1,
>     mpx_register_names = 0x0, zmm0h_regnum = 63,
>     k_register_names = 0xf5a900 <i386_k_names>,
>     zmmh_register_names = 0xf5a8a0 <i386_zmmh_names>,
>     xmm_avx512_register_names = 0x0, ymm_avx512_register_names = 0x0,
>     num_pkeys_regs = 0, pkru_regnum = -1, pkeys_register_names = 0x0,
>     fsbase_regnum = -1, tdesc = 0x197b410, register_reggroup_p = 0x7a9578
>        <i386_linux_register_reggroup_p(gdbarch*, int, reggroup const*)>,
>     jb_pc_offset = 20, struct_return = pcc_struct_return, sigtramp_start = 0x0,
>     sigtramp_end = 0x0,
>     sigtramp_p = 0x7a99ae <i386_linux_sigtramp_p(frame_info_ptr)>,
>     sigcontext_addr = 0x7a9c52 <i386_linux_sigcontext_addr(frame_info_ptr)>,
>     sc_reg_offset = 0x159fc60 <i386_linux_sc_reg_offset>, sc_num_regs = 16,
>     sc_pc_offset = -1, sc_sp_offset = -1, i386_mmx_type = 0x0,
>     i386_ymm_type = 0x0, i386_zmm_type = 0x0, i387_ext_type = 0x0,
>     i386_bnd_type = 0x0, record_regmap = 0xf5d5a0 <i386_record_regmap>,
>     i386_intx80_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>,
>     i386_sysenter_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>,
>     i386_syscall_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>, fpregset = 0xf5b5c0 <i386_fpregset>}

Hmm, so what I have been assuming is that you only get a tdesc with those register
sets if target::read_description (either x86_linux_nat_target::read_description
in x86-linux-nat.c for a native process or the gdbarch_core_read_description
handler in (i386|amd64)-linux-tdep.c) returns a tdesc with it, and the ones I just
mentioned all set a xsave_layout at the same time.  However, I think I had overlooked
the remote target.  That is, if you are connected to a remote target but want to
use gcore to write out a local core dump, that I think is the case that is breaking.

This case is a bit weird.  I had assumed I could avoid having to send the
layout across the remote protocol because the individual registers are
sent across the protocol and gdbserver is required to deal with the layout
and reinterpret the XSAVE "block" as individual registers.  However, to write
out a core dump note, we have to use some sort of XSAVE layout.  I could either
go back to making it a new TARGET_OBJECT and it could be fetched across the
wire from gdbserver (but only used for gcore, not for anything else), but
you still have a compatiblity problem in that old gdbserver's won't know about
it so you need a fallback based on the XCR0 mask.  Alternatively, we could
just always use a fallback in this case of picking a layout based on the XCR0
mask.  Previously this was always using the hardcoded Intel layout which is
why this worked before.

It's a bit of a shame to have to fetch it over the wire, but probably that is
the cleaner long term solution, even though it will require a fallback for now
to pick an arbitrary layout based on the XCR0 mask.

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-14 15:58 ` [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
@ 2023-07-26  8:31   ` Willgerodt, Felix
  0 siblings, 0 replies; 58+ messages in thread
From: Willgerodt, Felix @ 2023-07-26  8:31 UTC (permalink / raw)
  To: John Baldwin, gdb-patches; +Cc: George, Jini Susan

Hi John,

Just fyi, this week Intel announced APX:
https://www.intel.com/content/www/us/en/developer/articles/technical/advanced-performance-extensions-apx.html

It adds new GPRs. To cite from there:

"The new GPRs are XSAVE-enabled, which means that they can be automatically saved and restored by XSAVE/XRSTOR sequences during context switches.
They do not change the size and layout of the XSAVE area as they take up the space left behind by the deprecated Intel® MPX registers."

Not sure if that has any influence on your patch series, I thought it might be interesting for you anyway.

Regards,
Felix


> -----Original Message-----
> From: Gdb-patches <gdb-patches-
> bounces+felix.willgerodt=intel.com@sourceware.org> On Behalf Of John Baldwin
> Sent: Freitag, 14. Juli 2023 17:59
> To: gdb-patches@sourceware.org
> Cc: Joel Brobecker <brobecker@adacore.com>; George, Jini Susan
> <JiniSusan.George@amd.com>
> Subject: Re: [PATCH v6 00/15] Handle variable XSAVE layouts
> 
> On 7/14/23 8:51 AM, John Baldwin wrote:
> > Changes since V5:
> >
> > - A few fixes not tied to the new layout handling have been merged to
> >    master.
> >
> > - Reworded the comment describing i386_*_core_read_xsave_info in patches
> >    6 and 8.
> >
> > Aleksandar Paunovic (2):
> >    gdbserver: Refactor the legacy region within the xsave struct
> >    gdbserver: Use x86_xstate_layout to parse the XSAVE extended state
> >      area.
> >
> > John Baldwin (13):
> >    x86: Add an x86_xsave_layout structure to handle variable XSAVE
> >      layouts.
> >    gdb: Store an x86_xsave_layout in i386_gdbarch_tdep.
> >    core: Support fetching x86 XSAVE layout from architectures.
> >    nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count.
> >    x86 nat: Add helper functions to save the XSAVE layout for the host.
> >    gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
> >    gdb: Support XSAVE layouts for the current host in the FreeBSD x86
> >      targets.
> >    gdb: Update x86 Linux architectures to support XSAVE layouts.
> >    gdb: Support XSAVE layouts for the current host in the Linux x86
> >      targets.
> >    gdb: Use x86_xstate_layout to parse the XSAVE extended state area.
> >    gdbserver: Add a function to set the XSAVE mask and size.
> >    x86: Remove X86_XSTATE_SIZE and related constants.
> >    gdbserver: Simplify handling of ZMM registers.
> 
> I would like to get this series into GDB 14 if possible.  Without it one
> cannot examine certain XSAVE registers (e.g. YMM for AVX) in core dumps
> generated on modern AMD CPUs on both Linux and FreeBSD.
> 
> --
> John Baldwin

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle variable XSAVE layouts.
  2023-07-14 15:51 ` [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle " John Baldwin
@ 2023-07-26 19:22   ` Simon Marchi
  2023-07-26 21:27     ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 19:22 UTC (permalink / raw)
  To: John Baldwin, gdb-patches; +Cc: Aleksandar Paunovic

On 7/14/23 11:51, John Baldwin wrote:
> The standard layout of the XSAVE extended state area consists of three
> regions.  The first 512 bytes (legacy region) match the layout of the
> FXSAVE instruction including floating point registers, MMX registers,
> and SSE registers.  The next 64 bytes (XSAVE header) contains a header
> with a fixed layout.  The final region (extended region) contains zero
> or more optional state components.  Examples of these include the
> upper 128 bits of YMM registers for AVX.
> 
> These optional state components generally have an
> architecturally-fixed size, but they are not assigned architectural
> offsets in the extended region.  Instead, processors provide
> additional CPUID leafs describing the size and offset of each
> component in the "standard" layout for a given CPU.  (There is also a
> "compact" format which uses an alternate layout, but existing OS's
> currently export the "standard" layout when exporting XSAVE data via
> ptrace() and core dumps.)
> 
> To date, GDB has assumed the layout used on current Intel processors
> for state components in the extended region and hardcoded those
> offsets in the tables in i387-tdep.c and i387-fp.cc.  However, this
> fails on recent AMD processors which use a different layout.
> Specifically, AMD Zen3 and later processors do not leave space for the
> MPX register set in between the AVX and AVX512 register sets.
> 
> To rectify this, add an x86_xsave_layout structure which contains the
> total size of the XSAVE extended state area as well as the offset of
> each known optional state component.
> 
> Subsequent commits will modify XSAVE parsing in both gdb and gdbserver
> to use x86_xsave_layout.
> 
> Co-authored-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
> ---
>  gdbsupport/x86-xstate.h | 65 +++++++++++++++++++++++++++++++++++------
>  1 file changed, 56 insertions(+), 9 deletions(-)
> 
> diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
> index b8740fd8701..27fc0bd12f2 100644
> --- a/gdbsupport/x86-xstate.h
> +++ b/gdbsupport/x86-xstate.h
> @@ -20,22 +20,69 @@
>  #ifndef COMMON_X86_XSTATE_H
>  #define COMMON_X86_XSTATE_H
>  
> +/* The extended state feature IDs in the state component bitmap.  */
> +#define X86_XSTATE_X87_ID	0
> +#define X86_XSTATE_SSE_ID	1
> +#define X86_XSTATE_AVX_ID	2
> +#define X86_XSTATE_BNDREGS_ID	3
> +#define X86_XSTATE_BNDCFG_ID	4
> +#define X86_XSTATE_K_ID		5
> +#define X86_XSTATE_ZMM_H_ID	6
> +#define X86_XSTATE_ZMM_ID	7
> +#define X86_XSTATE_PKRU_ID	9
> +
>  /* The extended state feature bits.  */
> -#define X86_XSTATE_X87		(1ULL << 0)
> -#define X86_XSTATE_SSE		(1ULL << 1)
> -#define X86_XSTATE_AVX		(1ULL << 2)
> -#define X86_XSTATE_BNDREGS	(1ULL << 3)
> -#define X86_XSTATE_BNDCFG	(1ULL << 4)
> +#define X86_XSTATE_X87		(1ULL << X86_XSTATE_X87_ID)
> +#define X86_XSTATE_SSE		(1ULL << X86_XSTATE_SSE_ID)
> +#define X86_XSTATE_AVX		(1ULL << X86_XSTATE_AVX_ID)
> +#define X86_XSTATE_BNDREGS	(1ULL << X86_XSTATE_BNDREGS_ID)
> +#define X86_XSTATE_BNDCFG	(1ULL << X86_XSTATE_BNDCFG_ID)
>  #define X86_XSTATE_MPX		(X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG)
>  
>  /* AVX 512 adds three feature bits.  All three must be enabled.  */
> -#define X86_XSTATE_K		(1ULL << 5)
> -#define X86_XSTATE_ZMM_H	(1ULL << 6)
> -#define X86_XSTATE_ZMM		(1ULL << 7)
> +#define X86_XSTATE_K		(1ULL << X86_XSTATE_K_ID)
> +#define X86_XSTATE_ZMM_H	(1ULL << X86_XSTATE_ZMM_H_ID)
> +#define X86_XSTATE_ZMM		(1ULL << X86_XSTATE_ZMM_ID)
>  #define X86_XSTATE_AVX512	(X86_XSTATE_K | X86_XSTATE_ZMM_H \
>  				 | X86_XSTATE_ZMM)
>  
> -#define X86_XSTATE_PKRU		(1ULL << 9)
> +#define X86_XSTATE_PKRU		(1ULL << X86_XSTATE_PKRU_ID)
> +
> +/* Size and offsets of register states in the XSAVE area extended
> +   region.  Offsets are set to 0 to indicate the absence of the
> +   associated registers.  */

Extreme comment nitpick.  In "Size and offsets", one is singular and the
other is plural.  Should it be "Sizes and offsets", or "Size and
offset"?

In any case:

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 03/15] core: Support fetching x86 XSAVE layout from architectures.
  2023-07-14 15:51 ` [PATCH v6 03/15] core: Support fetching x86 XSAVE layout from architectures John Baldwin
@ 2023-07-26 19:37   ` Simon Marchi
  2023-07-26 21:28     ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 19:37 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> Add gdbarch_core_read_x86_xsave_layout to fetch the x86 XSAVE layout
> structure from a core file.
> 
> Current OS's do not export the offsets of XSAVE state components in
> core dumps, so provide an i387_set_xsave_layout helper function to set

Re-reading this after a few months, I wonder if naming this function
i387_guess_xsave_layout would make it a bit clearer.  "set" makes it
sound like it's a dumb setter (which it is not).

In any case:

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 04/15] nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count.
  2023-07-14 15:51 ` [PATCH v6 04/15] nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count John Baldwin
@ 2023-07-26 19:41   ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 19:41 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> ---
>  gdb/nat/x86-cpuid.h | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/gdb/nat/x86-cpuid.h b/gdb/nat/x86-cpuid.h
> index 0955afba577..517113d45e8 100644
> --- a/gdb/nat/x86-cpuid.h
> +++ b/gdb/nat/x86-cpuid.h
> @@ -48,6 +48,30 @@ x86_cpuid (unsigned int __level,
>    return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
>  }
>  
> +/* Return cpuid data for requested cpuid level and sub-level, as found
> +   in returned eax, ebx, ecx and edx registers.  The function checks
> +   if cpuid is supported and returns 1 for valid cpuid information or
> +   0 for unsupported cpuid level.  Pointers may be non-null.  */
> +
> +static __inline int
> +x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
> +		 unsigned int *__eax, unsigned int *__ebx,
> +		 unsigned int *__ecx, unsigned int *__edx)
> +{
> +  unsigned int __scratch;
> +
> +  if (__eax == nullptr)
> +    __eax = &__scratch;
> +  if (__ebx == nullptr)
> +    __ebx = &__scratch;
> +  if (__ecx == nullptr)
> +    __ecx = &__scratch;
> +  if (__edx == nullptr)
> +    __edx = &__scratch;
> +
> +  return __get_cpuid_count (__level, __sublevel, __eax, __ebx, __ecx, __edx);
> +}
> +
>  #else
>  
>  static __inline int
> @@ -58,6 +82,14 @@ x86_cpuid (unsigned int __level,
>    return 0;
>  }
>  
> +static __inline int
> +x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
> +		 unsigned int *__eax, unsigned int *__ebx,
> +		 unsigned int *__ecx, unsigned int *__edx)
> +{
> +  return 0;
> +}
> +
>  #endif /* i386 && x86_64 */
>  
>  #endif /* NAT_X86_CPUID_H */
> -- 
> 2.40.0
> 

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 05/15] x86 nat: Add helper functions to save the XSAVE layout for the host.
  2023-07-14 15:51 ` [PATCH v6 05/15] x86 nat: Add helper functions to save the XSAVE layout for the host John Baldwin
@ 2023-07-26 19:48   ` Simon Marchi
  2023-07-26 21:37     ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 19:48 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> x86_xsave_length returns the total length of the XSAVE state area
> standard format as queried from CPUID.
> 
> x86_fetch_xsave_layout uses CPUID to query the offsets of XSAVE
> extended regions from the running host.  The total length of the XSAVE
> state area can either be supplied the caller if known (e.g. from

"supplied by the caller"?

Otherwise:

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
  2023-07-14 15:51 ` [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts John Baldwin
@ 2023-07-26 20:04   ` Simon Marchi
  2023-07-26 21:43     ` John Baldwin
  2023-07-28 21:23   ` [PATCH v6a " John Baldwin
  1 sibling, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 20:04 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

> @@ -241,43 +241,49 @@ static const struct tramp_frame i386_fbsd64_sigframe =
>    i386_fbsd_sigframe_init
>  };
>  
> -/* Get XSAVE extended state xcr0 from core dump.  */
> +/* See i386-fbsd-tdep.h.  */
>  
>  uint64_t
> -i386fbsd_core_read_xcr0 (bfd *abfd)
> +i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
>  {
>    asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
> -  uint64_t xcr0;
> +  if (xstate == nullptr)
> +    return X86_XSTATE_SSE_MASK;
>  
> -  if (xstate)
> +  /* Check extended state size.  */
> +  size_t size = bfd_section_size (xstate);
> +  if (size < X86_XSTATE_AVX_SIZE)
> +    return X86_XSTATE_SSE_MASK;
> +
> +  char contents[8];
> +  if (! bfd_get_section_contents (abfd, xstate, contents,
> +				  I386_FBSD_XSAVE_XCR0_OFFSET, 8))
>      {
> -      size_t size = bfd_section_size (xstate);
> -
> -      /* Check extended state size.  */
> -      if (size < X86_XSTATE_AVX_SIZE)
> -	xcr0 = X86_XSTATE_SSE_MASK;
> -      else
> -	{
> -	  char contents[8];
> -
> -	  if (! bfd_get_section_contents (abfd, xstate, contents,
> -					  I386_FBSD_XSAVE_XCR0_OFFSET,
> -					  8))
> -	    {
> -	      warning (_("Couldn't read `xcr0' bytes from "
> -			 "`.reg-xstate' section in core file."));
> -	      return X86_XSTATE_SSE_MASK;
> -	    }
> -
> -	  xcr0 = bfd_get_64 (abfd, contents);
> -	}
> +      warning (_("Couldn't read `xcr0' bytes from "
> +		 "`.reg-xstate' section in core file."));
> +      return X86_XSTATE_SSE_MASK;
>      }
> -  else
> -    xcr0 = X86_XSTATE_SSE_MASK;
> +
> +  uint64_t xcr0 = bfd_get_64 (abfd, contents);
> +
> +  if (!i387_set_xsave_layout (xcr0, size, layout))
> +    return X86_XSTATE_SSE_MASK;
>  
>    return xcr0;
>  }
>  
> +/* Implement the core_read_x86_xsave_layout gdbarch method.  */
Should be:

/* See i386-fbsd-tdep.h.  */

> +
> +bool
> +i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
> +				      x86_xsave_layout &layout)
> +{
> +  if (i386_fbsd_core_read_xsave_info (core_bfd, layout) == X86_XSTATE_SSE_MASK)
> +    return false;
> +
> +  return true;
> +}

Rewrite as

  return i386_fbsd_core_read_xsave_info (core_bfd, layout) != X86_XSTATE_SSE_MASK;

?

Otherwise:

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 07/15] gdb: Support XSAVE layouts for the current host in the FreeBSD x86 targets.
  2023-07-14 15:51 ` [PATCH v6 07/15] gdb: Support XSAVE layouts for the current host in the FreeBSD x86 targets John Baldwin
@ 2023-07-26 20:26   ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 20:26 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> Use the CPUID instruction to fetch the offsets of supported state
> components.

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-14 15:51 ` [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts John Baldwin
@ 2023-07-26 20:45   ` Simon Marchi
  2023-07-26 21:16     ` John Baldwin
  2023-07-28 21:29   ` [PATCH v6a " John Baldwin
  1 sibling, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 20:45 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

> diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
> index 554c1455a5f..f27efbb1d59 100644
> --- a/gdb/i386-linux-tdep.c
> +++ b/gdb/i386-linux-tdep.c
> @@ -638,45 +638,51 @@ static int i386_linux_sc_reg_offset[] =
>    0 * 4				/* %gs */
>  };
>  
> -/* Get XSAVE extended state xcr0 from core dump.  */
> +/* See i386-linux-tdep.h.  */
>  
>  uint64_t
> -i386_linux_core_read_xcr0 (bfd *abfd)
> +i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
>  {
>    asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
> -  uint64_t xcr0;
> +  if (xstate == nullptr)
> +    return X86_XSTATE_SSE_MASK;
>  
> -  if (xstate)
> +  /* Check extended state size.  */
> +  size_t size = bfd_section_size (xstate);
> +  if (size < X86_XSTATE_AVX_SIZE)
> +    return X86_XSTATE_SSE_MASK;
> +
> +  char contents[8];
> +  if (! bfd_get_section_contents (abfd, xstate, contents,
> +				  I386_LINUX_XSAVE_XCR0_OFFSET, 8))
>      {
> -      size_t size = bfd_section_size (xstate);
> -
> -      /* Check extended state size.  */
> -      if (size < X86_XSTATE_AVX_SIZE)
> -	xcr0 = X86_XSTATE_SSE_MASK;
> -      else
> -	{
> -	  char contents[8];
> -
> -	  if (! bfd_get_section_contents (abfd, xstate, contents,
> -					  I386_LINUX_XSAVE_XCR0_OFFSET,
> -					  8))
> -	    {
> -	      warning (_("Couldn't read `xcr0' bytes from "
> -			 "`.reg-xstate' section in core file."));
> -	      return 0;
> -	    }
> -
> -	  xcr0 = bfd_get_64 (abfd, contents);
> -	}
> +      warning (_("Couldn't read `xcr0' bytes from "
> +		 "`.reg-xstate' section in core file."));
> +      return X86_XSTATE_SSE_MASK;
>      }
> -  else
> -    xcr0 = 0;
> +
> +  uint64_t xcr0 = bfd_get_64 (abfd, contents);
> +
> +  if (!i387_set_xsave_layout (xcr0, size, layout))
> +    return X86_XSTATE_SSE_MASK;
>  
>    return xcr0;
>  }

I think I spotted a change of behavior in
i386_linux_core_read_xsave_info, which has consequences down the line.

If there's no .reg-xstate section, we would previously return xcr0 == 0,
i386_linux_read_description would return nullptr, and we would choose
between X87 and SSE based on .reg-xfp.

After the patch, i386_linux_core_read_xsave_info returns SSE, meaning
we'll never reach the point that checks for .reg-xfp.

Maybe the first return (if there's not .reg-xstate section) should
return 0?

>  
>  /* See i386-linux-tdep.h.  */
>  
> +bool
> +i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
> +				       x86_xsave_layout &layout)
> +{
> +  if (i386_linux_core_read_xsave_info (core_bfd, layout) == X86_XSTATE_SSE_MASK)
> +    return false;
> +
> +  return true;
> +}

Same as earlier, could be:

    return i386_linux_core_read_xsave_info (core_bfd, layout) != X86_XSTATE_SSE_MASK;

... although if i386_linux_core_read_xsave_info can return 0, we'd need
to check for that too.

Simon


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 09/15] gdb: Support XSAVE layouts for the current host in the Linux x86 targets.
  2023-07-14 15:51 ` [PATCH v6 09/15] gdb: Support XSAVE layouts for the current host in the Linux x86 targets John Baldwin
@ 2023-07-26 20:51   ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 20:51 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> 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>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-26 20:45   ` Simon Marchi
@ 2023-07-26 21:16     ` John Baldwin
  2023-07-27 21:48       ` Simon Marchi
  0 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-26 21:16 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 7/26/23 1:45 PM, Simon Marchi wrote:
>> diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
>> index 554c1455a5f..f27efbb1d59 100644
>> --- a/gdb/i386-linux-tdep.c
>> +++ b/gdb/i386-linux-tdep.c
>> @@ -638,45 +638,51 @@ static int i386_linux_sc_reg_offset[] =
>>     0 * 4				/* %gs */
>>   };
>>   
>> -/* Get XSAVE extended state xcr0 from core dump.  */
>> +/* See i386-linux-tdep.h.  */
>>   
>>   uint64_t
>> -i386_linux_core_read_xcr0 (bfd *abfd)
>> +i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
>>   {
>>     asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
>> -  uint64_t xcr0;
>> +  if (xstate == nullptr)
>> +    return X86_XSTATE_SSE_MASK;
>>   
>> -  if (xstate)
>> +  /* Check extended state size.  */
>> +  size_t size = bfd_section_size (xstate);
>> +  if (size < X86_XSTATE_AVX_SIZE)
>> +    return X86_XSTATE_SSE_MASK;
>> +
>> +  char contents[8];
>> +  if (! bfd_get_section_contents (abfd, xstate, contents,
>> +				  I386_LINUX_XSAVE_XCR0_OFFSET, 8))
>>       {
>> -      size_t size = bfd_section_size (xstate);
>> -
>> -      /* Check extended state size.  */
>> -      if (size < X86_XSTATE_AVX_SIZE)
>> -	xcr0 = X86_XSTATE_SSE_MASK;
>> -      else
>> -	{
>> -	  char contents[8];
>> -
>> -	  if (! bfd_get_section_contents (abfd, xstate, contents,
>> -					  I386_LINUX_XSAVE_XCR0_OFFSET,
>> -					  8))
>> -	    {
>> -	      warning (_("Couldn't read `xcr0' bytes from "
>> -			 "`.reg-xstate' section in core file."));
>> -	      return 0;
>> -	    }
>> -
>> -	  xcr0 = bfd_get_64 (abfd, contents);
>> -	}
>> +      warning (_("Couldn't read `xcr0' bytes from "
>> +		 "`.reg-xstate' section in core file."));
>> +      return X86_XSTATE_SSE_MASK;
>>       }
>> -  else
>> -    xcr0 = 0;
>> +
>> +  uint64_t xcr0 = bfd_get_64 (abfd, contents);
>> +
>> +  if (!i387_set_xsave_layout (xcr0, size, layout))
>> +    return X86_XSTATE_SSE_MASK;
>>   
>>     return xcr0;
>>   }
> 
> I think I spotted a change of behavior in
> i386_linux_core_read_xsave_info, which has consequences down the line.
> 
> If there's no .reg-xstate section, we would previously return xcr0 == 0,
> i386_linux_read_description would return nullptr, and we would choose
> between X87 and SSE based on .reg-xfp.
> 
> After the patch, i386_linux_core_read_xsave_info returns SSE, meaning
> we'll never reach the point that checks for .reg-xfp.
> 
> Maybe the first return (if there's not .reg-xstate section) should
> return 0?

Ooo, that's a good catch.  This function is shared with amd64, so I think
it's best if it keeps returning an xcr0 value, but we could patch
i386_linux_core_read_description to instead do this:

static const struct target_desc *
i386_linux_core_read_description (struct gdbarch *gdbarch,
				  struct target_ops *target,
				  bfd *abfd)
{
   /* Linux/i386.  */
   x86_xsave_layout layout;
   uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
   if (xcr0 == X86_XSTATE_X87_MASK
       && bfd_get_section_by_name (abfd, ".reg-xfp") != NULL)
     xcr0 = X86_XSTATE_SSE_MASK;

   return i386_linux_read_description (xcr0);
}

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle variable XSAVE layouts.
  2023-07-26 19:22   ` Simon Marchi
@ 2023-07-26 21:27     ` John Baldwin
  2023-07-26 22:51       ` Simon Marchi
  0 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-26 21:27 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches; +Cc: Aleksandar Paunovic

On 7/26/23 12:22 PM, Simon Marchi wrote:
> On 7/14/23 11:51, John Baldwin wrote:
>> The standard layout of the XSAVE extended state area consists of three
>> regions.  The first 512 bytes (legacy region) match the layout of the
>> FXSAVE instruction including floating point registers, MMX registers,
>> and SSE registers.  The next 64 bytes (XSAVE header) contains a header
>> with a fixed layout.  The final region (extended region) contains zero
>> or more optional state components.  Examples of these include the
>> upper 128 bits of YMM registers for AVX.
>>
>> These optional state components generally have an
>> architecturally-fixed size, but they are not assigned architectural
>> offsets in the extended region.  Instead, processors provide
>> additional CPUID leafs describing the size and offset of each
>> component in the "standard" layout for a given CPU.  (There is also a
>> "compact" format which uses an alternate layout, but existing OS's
>> currently export the "standard" layout when exporting XSAVE data via
>> ptrace() and core dumps.)
>>
>> To date, GDB has assumed the layout used on current Intel processors
>> for state components in the extended region and hardcoded those
>> offsets in the tables in i387-tdep.c and i387-fp.cc.  However, this
>> fails on recent AMD processors which use a different layout.
>> Specifically, AMD Zen3 and later processors do not leave space for the
>> MPX register set in between the AVX and AVX512 register sets.
>>
>> To rectify this, add an x86_xsave_layout structure which contains the
>> total size of the XSAVE extended state area as well as the offset of
>> each known optional state component.
>>
>> Subsequent commits will modify XSAVE parsing in both gdb and gdbserver
>> to use x86_xsave_layout.
>>
>> Co-authored-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
>> ---
>>   gdbsupport/x86-xstate.h | 65 +++++++++++++++++++++++++++++++++++------
>>   1 file changed, 56 insertions(+), 9 deletions(-)
>>
>> diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
>> index b8740fd8701..27fc0bd12f2 100644
>> --- a/gdbsupport/x86-xstate.h
>> +++ b/gdbsupport/x86-xstate.h
>> @@ -20,22 +20,69 @@
>>   #ifndef COMMON_X86_XSTATE_H
>>   #define COMMON_X86_XSTATE_H
>>   
>> +/* The extended state feature IDs in the state component bitmap.  */
>> +#define X86_XSTATE_X87_ID	0
>> +#define X86_XSTATE_SSE_ID	1
>> +#define X86_XSTATE_AVX_ID	2
>> +#define X86_XSTATE_BNDREGS_ID	3
>> +#define X86_XSTATE_BNDCFG_ID	4
>> +#define X86_XSTATE_K_ID		5
>> +#define X86_XSTATE_ZMM_H_ID	6
>> +#define X86_XSTATE_ZMM_ID	7
>> +#define X86_XSTATE_PKRU_ID	9
>> +
>>   /* The extended state feature bits.  */
>> -#define X86_XSTATE_X87		(1ULL << 0)
>> -#define X86_XSTATE_SSE		(1ULL << 1)
>> -#define X86_XSTATE_AVX		(1ULL << 2)
>> -#define X86_XSTATE_BNDREGS	(1ULL << 3)
>> -#define X86_XSTATE_BNDCFG	(1ULL << 4)
>> +#define X86_XSTATE_X87		(1ULL << X86_XSTATE_X87_ID)
>> +#define X86_XSTATE_SSE		(1ULL << X86_XSTATE_SSE_ID)
>> +#define X86_XSTATE_AVX		(1ULL << X86_XSTATE_AVX_ID)
>> +#define X86_XSTATE_BNDREGS	(1ULL << X86_XSTATE_BNDREGS_ID)
>> +#define X86_XSTATE_BNDCFG	(1ULL << X86_XSTATE_BNDCFG_ID)
>>   #define X86_XSTATE_MPX		(X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG)
>>   
>>   /* AVX 512 adds three feature bits.  All three must be enabled.  */
>> -#define X86_XSTATE_K		(1ULL << 5)
>> -#define X86_XSTATE_ZMM_H	(1ULL << 6)
>> -#define X86_XSTATE_ZMM		(1ULL << 7)
>> +#define X86_XSTATE_K		(1ULL << X86_XSTATE_K_ID)
>> +#define X86_XSTATE_ZMM_H	(1ULL << X86_XSTATE_ZMM_H_ID)
>> +#define X86_XSTATE_ZMM		(1ULL << X86_XSTATE_ZMM_ID)
>>   #define X86_XSTATE_AVX512	(X86_XSTATE_K | X86_XSTATE_ZMM_H \
>>   				 | X86_XSTATE_ZMM)
>>   
>> -#define X86_XSTATE_PKRU		(1ULL << 9)
>> +#define X86_XSTATE_PKRU		(1ULL << X86_XSTATE_PKRU_ID)
>> +
>> +/* Size and offsets of register states in the XSAVE area extended
>> +   region.  Offsets are set to 0 to indicate the absence of the
>> +   associated registers.  */
> 
> Extreme comment nitpick.  In "Size and offsets", one is singular and the
> other is plural.  Should it be "Sizes and offsets", or "Size and
> offset"?

Ah, there's a single size and multiple offsets.  Is this version clearer:

/* Total size of the XSAVE area extended region and offsets of
    register states within the region.  Offsets are set to 0 to
    indicate the absence of the associated registers.  */

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 03/15] core: Support fetching x86 XSAVE layout from architectures.
  2023-07-26 19:37   ` Simon Marchi
@ 2023-07-26 21:28     ` John Baldwin
  0 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-26 21:28 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 7/26/23 12:37 PM, Simon Marchi wrote:
> On 7/14/23 11:51, John Baldwin wrote:
>> Add gdbarch_core_read_x86_xsave_layout to fetch the x86 XSAVE layout
>> structure from a core file.
>>
>> Current OS's do not export the offsets of XSAVE state components in
>> core dumps, so provide an i387_set_xsave_layout helper function to set
> 
> Re-reading this after a few months, I wonder if naming this function
> i387_guess_xsave_layout would make it a bit clearer.  "set" makes it
> sound like it's a dumb setter (which it is not).

Yeah, that probably is a bit clearer, so I will rename it.

> In any case:
> 
> Approved-By: Simon Marchi <simon.marchi@efficios.com>
> 
> Simon

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 05/15] x86 nat: Add helper functions to save the XSAVE layout for the host.
  2023-07-26 19:48   ` Simon Marchi
@ 2023-07-26 21:37     ` John Baldwin
  0 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-26 21:37 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 7/26/23 12:48 PM, Simon Marchi wrote:
> On 7/14/23 11:51, John Baldwin wrote:
>> x86_xsave_length returns the total length of the XSAVE state area
>> standard format as queried from CPUID.
>>
>> x86_fetch_xsave_layout uses CPUID to query the offsets of XSAVE
>> extended regions from the running host.  The total length of the XSAVE
>> state area can either be supplied the caller if known (e.g. from
> 
> "supplied by the caller"?

Oops, yes, thanks.

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
  2023-07-26 20:04   ` Simon Marchi
@ 2023-07-26 21:43     ` John Baldwin
  0 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-26 21:43 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 7/26/23 1:04 PM, Simon Marchi wrote:
>> @@ -241,43 +241,49 @@ static const struct tramp_frame i386_fbsd64_sigframe =
>>     i386_fbsd_sigframe_init
>>   };
>>   
>> -/* Get XSAVE extended state xcr0 from core dump.  */
>> +/* See i386-fbsd-tdep.h.  */
>>   
>>   uint64_t
>> -i386fbsd_core_read_xcr0 (bfd *abfd)
>> +i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
>>   {
>>     asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
>> -  uint64_t xcr0;
>> +  if (xstate == nullptr)
>> +    return X86_XSTATE_SSE_MASK;
>>   
>> -  if (xstate)
>> +  /* Check extended state size.  */
>> +  size_t size = bfd_section_size (xstate);
>> +  if (size < X86_XSTATE_AVX_SIZE)
>> +    return X86_XSTATE_SSE_MASK;
>> +
>> +  char contents[8];
>> +  if (! bfd_get_section_contents (abfd, xstate, contents,
>> +				  I386_FBSD_XSAVE_XCR0_OFFSET, 8))
>>       {
>> -      size_t size = bfd_section_size (xstate);
>> -
>> -      /* Check extended state size.  */
>> -      if (size < X86_XSTATE_AVX_SIZE)
>> -	xcr0 = X86_XSTATE_SSE_MASK;
>> -      else
>> -	{
>> -	  char contents[8];
>> -
>> -	  if (! bfd_get_section_contents (abfd, xstate, contents,
>> -					  I386_FBSD_XSAVE_XCR0_OFFSET,
>> -					  8))
>> -	    {
>> -	      warning (_("Couldn't read `xcr0' bytes from "
>> -			 "`.reg-xstate' section in core file."));
>> -	      return X86_XSTATE_SSE_MASK;
>> -	    }
>> -
>> -	  xcr0 = bfd_get_64 (abfd, contents);
>> -	}
>> +      warning (_("Couldn't read `xcr0' bytes from "
>> +		 "`.reg-xstate' section in core file."));
>> +      return X86_XSTATE_SSE_MASK;
>>       }
>> -  else
>> -    xcr0 = X86_XSTATE_SSE_MASK;
>> +
>> +  uint64_t xcr0 = bfd_get_64 (abfd, contents);
>> +
>> +  if (!i387_set_xsave_layout (xcr0, size, layout))
>> +    return X86_XSTATE_SSE_MASK;
>>   
>>     return xcr0;
>>   }
>>   
>> +/* Implement the core_read_x86_xsave_layout gdbarch method.  */
> Should be:
> 
> /* See i386-fbsd-tdep.h.  */

Fixed.

>> +
>> +bool
>> +i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
>> +				      x86_xsave_layout &layout)
>> +{
>> +  if (i386_fbsd_core_read_xsave_info (core_bfd, layout) == X86_XSTATE_SSE_MASK)
>> +    return false;
>> +
>> +  return true;
>> +}
> 
> Rewrite as
> 
>    return i386_fbsd_core_read_xsave_info (core_bfd, layout) != X86_XSTATE_SSE_MASK;
> 
> ?

Yes, and I'll fix it in i386-linux-tdep.c as well.

> Otherwise:
> 
> Approved-By: Simon Marchi <simon.marchi@efficios.com>
> 
> Simon
> 

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-25 22:05           ` John Baldwin
@ 2023-07-26 22:31             ` John Baldwin
  2023-07-27 21:36               ` Keith Seitz
  0 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-26 22:31 UTC (permalink / raw)
  To: gdb-patches

On 7/25/23 3:05 PM, John Baldwin wrote:
> On 7/25/23 1:42 PM, Keith Seitz wrote:
>> On 7/25/23 11:59, John Baldwin wrote:
>>>
>>> Hopefully it triggers the assertion, and then what will be useful is to see what
>>> features the tdesc contains ('info locals' would cover that if they aren't all
>>> optimized out).
>>
>> Yes, that assertion does trigger (on all -m32 targets).
>>
>>    From the native-gdbserver/-m32 case at the assertion (I have a debug build):
>>
>> (top-gdb) info locals
>> tdesc = 0x197b410
>> feature_core = 0x197d5a0
>> feature_sse = 0x1987200
>> feature_avx = 0x1989db0
>> feature_mpx = 0x0
>> feature_avx512 = 0x198a310
>> feature_pkeys = 0x198aec0
>> feature_segments = 0x0
>> i = 0
>> num_regs = 32767
>> valid_p = 1
>> __func__ = "i386_validate_tdesc_p"
>> (top-gdb) p *tdep
>> $2 = {<gdbarch_tdep_base> = {
>>        _vptr.gdbarch_tdep_base = 0xf5df38 <vtable for i386_gdbarch_tdep+16>},
>>      gregset_reg_offset = 0x159fb20 <i386_linux_gregset_reg_offset>,
>>      gregset_num_regs = 73, sizeof_gregset = 68, sizeof_fpregset = 108,
>>      st0_regnum = 16, num_mmx_regs = 8, mm0_regnum = 0, num_ymm_regs = 0,
>>      ymm0_regnum = 0, num_k_regs = 0, k0_regnum = 55, num_zmm_regs = 8,
>>      zmm0_regnum = 0, num_byte_regs = 8, al_regnum = 0, num_word_regs = 8,
>>      ax_regnum = 0, num_dword_regs = 0, eax_regnum = 0, num_core_regs = 32,
>>      num_xmm_regs = 8, num_xmm_avx512_regs = 0, xmm16_regnum = -1,
>>      num_ymm_avx512_regs = 0, ymm16_regnum = 0, xcr0 = 231,
>>      xsave_xcr0_offset = 464, xsave_layout = {sizeof_xsave = 0, avx_offset = 0,
>>        bndregs_offset = 0, bndcfg_offset = 0, k_offset = 0, zmm_h_offset = 0,
>>        zmm_offset = 0, pkru_offset = 0},
>>      register_names = 0xf5a6a0 <i386_register_names>, ymm0h_regnum = -1,
>>      ymmh_register_names = 0x0, ymm16h_regnum = -1, ymm16h_register_names = 0x0,
>>      bnd0r_regnum = -1, bnd0_regnum = 0, bndcfgu_regnum = -1,
>>      mpx_register_names = 0x0, zmm0h_regnum = 63,
>>      k_register_names = 0xf5a900 <i386_k_names>,
>>      zmmh_register_names = 0xf5a8a0 <i386_zmmh_names>,
>>      xmm_avx512_register_names = 0x0, ymm_avx512_register_names = 0x0,
>>      num_pkeys_regs = 0, pkru_regnum = -1, pkeys_register_names = 0x0,
>>      fsbase_regnum = -1, tdesc = 0x197b410, register_reggroup_p = 0x7a9578
>>         <i386_linux_register_reggroup_p(gdbarch*, int, reggroup const*)>,
>>      jb_pc_offset = 20, struct_return = pcc_struct_return, sigtramp_start = 0x0,
>>      sigtramp_end = 0x0,
>>      sigtramp_p = 0x7a99ae <i386_linux_sigtramp_p(frame_info_ptr)>,
>>      sigcontext_addr = 0x7a9c52 <i386_linux_sigcontext_addr(frame_info_ptr)>,
>>      sc_reg_offset = 0x159fc60 <i386_linux_sc_reg_offset>, sc_num_regs = 16,
>>      sc_pc_offset = -1, sc_sp_offset = -1, i386_mmx_type = 0x0,
>>      i386_ymm_type = 0x0, i386_zmm_type = 0x0, i387_ext_type = 0x0,
>>      i386_bnd_type = 0x0, record_regmap = 0xf5d5a0 <i386_record_regmap>,
>>      i386_intx80_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>,
>>      i386_sysenter_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>,
>>      i386_syscall_record = 0x7aa2fc <i386_linux_intx80_sysenter_syscall_record(regcache*)>, fpregset = 0xf5b5c0 <i386_fpregset>}
> 
> Hmm, so what I have been assuming is that you only get a tdesc with those register
> sets if target::read_description (either x86_linux_nat_target::read_description
> in x86-linux-nat.c for a native process or the gdbarch_core_read_description
> handler in (i386|amd64)-linux-tdep.c) returns a tdesc with it, and the ones I just
> mentioned all set a xsave_layout at the same time.  However, I think I had overlooked
> the remote target.  That is, if you are connected to a remote target but want to
> use gcore to write out a local core dump, that I think is the case that is breaking.
> 
> This case is a bit weird.  I had assumed I could avoid having to send the
> layout across the remote protocol because the individual registers are
> sent across the protocol and gdbserver is required to deal with the layout
> and reinterpret the XSAVE "block" as individual registers.  However, to write
> out a core dump note, we have to use some sort of XSAVE layout.  I could either
> go back to making it a new TARGET_OBJECT and it could be fetched across the
> wire from gdbserver (but only used for gcore, not for anything else), but
> you still have a compatiblity problem in that old gdbserver's won't know about
> it so you need a fallback based on the XCR0 mask.  Alternatively, we could
> just always use a fallback in this case of picking a layout based on the XCR0
> mask.  Previously this was always using the hardcoded Intel layout which is
> why this worked before.
> 
> It's a bit of a shame to have to fetch it over the wire, but probably that is
> the cleaner long term solution, even though it will require a fallback for now
> to pick an arbitrary layout based on the XCR0 mask.

So I have a couple of things to try here.  First, a simple fix for the crash
is this change (relative to the branch), but it does mean the core dumps generated
by gcore for a remote target will not contain extended XSAVE state like AVX, etc.:

diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index c8b467a0416..a7d61f33a08 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -768,7 +768,7 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
  
    cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
  
-  if (tdep->xcr0 & X86_XSTATE_AVX)
+  if (tdep->xsave_layout.sizeof_xsave != 0)
      cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
         tdep->xsave_layout.sizeof_xsave, &i386_linux_xstateregset,
         "XSAVE extended state", cb_data);

Arguably that is more correct as it lines up with the way the rest of the x86 arches
in this series.

The other change I have locally is one to generate a "fallback" layout to use in
this case that a target (such as remote) doesn't provide a layout.  I'm still not
quite happy with what I would want to do over the wire.  In some ways I'd rather
have a way to send across CPUID requests to mimic what we do for live processes
to determine the layout.  I really don't want to encode a binary form of the
current structure as it will likely change in the future for new XSAVE regions.
Perhaps an XML blob that described the total size and the size and offset of each
region could work.  Still, you would always need a fallback for old servers.

The fallback change:

diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index d5423681802..30968522824 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8773,6 +8773,14 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        gdbarch_free (gdbarch);
        return NULL;
      }
+
+  /* If the target didn't provide an XSAVE layout, generate a fallback
+     layout.  This currently happens with remote targets and is used
+     to determine the layout of the XSAVE register notes when
+     generating a core dump.  */
+  if (tdep->xcr0 != X86_XSTATE_X87_MASK && tdep->xcr0 != X86_XSTATE_SSE_MASK
+      && xsave_layout.sizeof_xsave == 0)
+    xsave_layout = i387_fallback_xsave_layout (tdep->xcr0);
    tdep->xsave_layout = xsave_layout;
  
    num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 47667da21c7..90bd7a5db9e 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -987,6 +987,48 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
    return true;
  }
  
+/* See i387-tdep.h.  */
+
+x86_xsave_layout
+i387_fallback_xsave_layout (uint64_t xcr0)
+{
+  x86_xsave_layout layout;
+  if (HAS_PKRU (xcr0))
+    {
+      layout.sizeof_xsave = 2696;
+      layout.avx_offset = 576;
+      layout.bndregs_offset = 960;
+      layout.bndcfg_offset = 1024;
+      layout.k_offset = 1088;
+      layout.zmm_h_offset = 1152;
+      layout.zmm_offset = 1664;
+      layout.pkru_offset = 2688;
+    }
+  else if (HAS_AVX512 (xcr0))
+    {
+      layout.sizeof_xsave = 2688;
+      layout.avx_offset = 576;
+      layout.bndregs_offset = 960;
+      layout.bndcfg_offset = 1024;
+      layout.k_offset = 1088;
+      layout.zmm_h_offset = 1152;
+      layout.zmm_offset = 1664;
+    }
+  else if (HAS_MPX (xcr0))
+    {
+      layout.sizeof_xsave = 1088;
+      layout.avx_offset = 576;
+      layout.bndregs_offset = 960;
+      layout.bndcfg_offset = 1024;
+    }
+  else
+    {
+      layout.sizeof_xsave = 832;
+      layout.avx_offset = 576;
+    }
+  return layout;
+}
+
  /* Extract from XSAVE a bitset of the features that are available on the
     target, but which have not yet been enabled.  */
  
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index e149e30e52e..8de68d00f6e 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -147,6 +147,10 @@ extern void i387_supply_fxsave (struct regcache *regcache, int regnum,
  extern bool i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
                                      x86_xsave_layout &layout);
  
+/* Generate a fallback XSAVE layout based on the XCR0 bitmask.  */
+
+extern x86_xsave_layout i387_fallback_xsave_layout (uint64_t xcr0);
+
  /* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
  
  extern void i387_supply_xsave (struct regcache *regcache, int regnum,


-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle variable XSAVE layouts.
  2023-07-26 21:27     ` John Baldwin
@ 2023-07-26 22:51       ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-07-26 22:51 UTC (permalink / raw)
  To: John Baldwin, gdb-patches; +Cc: Aleksandar Paunovic



On July 26, 2023 5:27:41 p.m. EDT, John Baldwin <jhb@FreeBSD.org> wrote:
>On 7/26/23 12:22 PM, Simon Marchi wrote:
>> On 7/14/23 11:51, John Baldwin wrote:
>>> The standard layout of the XSAVE extended state area consists of three
>>> regions.  The first 512 bytes (legacy region) match the layout of the
>>> FXSAVE instruction including floating point registers, MMX registers,
>>> and SSE registers.  The next 64 bytes (XSAVE header) contains a header
>>> with a fixed layout.  The final region (extended region) contains zero
>>> or more optional state components.  Examples of these include the
>>> upper 128 bits of YMM registers for AVX.
>>> 
>>> These optional state components generally have an
>>> architecturally-fixed size, but they are not assigned architectural
>>> offsets in the extended region.  Instead, processors provide
>>> additional CPUID leafs describing the size and offset of each
>>> component in the "standard" layout for a given CPU.  (There is also a
>>> "compact" format which uses an alternate layout, but existing OS's
>>> currently export the "standard" layout when exporting XSAVE data via
>>> ptrace() and core dumps.)
>>> 
>>> To date, GDB has assumed the layout used on current Intel processors
>>> for state components in the extended region and hardcoded those
>>> offsets in the tables in i387-tdep.c and i387-fp.cc.  However, this
>>> fails on recent AMD processors which use a different layout.
>>> Specifically, AMD Zen3 and later processors do not leave space for the
>>> MPX register set in between the AVX and AVX512 register sets.
>>> 
>>> To rectify this, add an x86_xsave_layout structure which contains the
>>> total size of the XSAVE extended state area as well as the offset of
>>> each known optional state component.
>>> 
>>> Subsequent commits will modify XSAVE parsing in both gdb and gdbserver
>>> to use x86_xsave_layout.
>>> 
>>> Co-authored-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
>>> ---
>>>   gdbsupport/x86-xstate.h | 65 +++++++++++++++++++++++++++++++++++------
>>>   1 file changed, 56 insertions(+), 9 deletions(-)
>>> 
>>> diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
>>> index b8740fd8701..27fc0bd12f2 100644
>>> --- a/gdbsupport/x86-xstate.h
>>> +++ b/gdbsupport/x86-xstate.h
>>> @@ -20,22 +20,69 @@
>>>   #ifndef COMMON_X86_XSTATE_H
>>>   #define COMMON_X86_XSTATE_H
>>>   +/* The extended state feature IDs in the state component bitmap.  */
>>> +#define X86_XSTATE_X87_ID	0
>>> +#define X86_XSTATE_SSE_ID	1
>>> +#define X86_XSTATE_AVX_ID	2
>>> +#define X86_XSTATE_BNDREGS_ID	3
>>> +#define X86_XSTATE_BNDCFG_ID	4
>>> +#define X86_XSTATE_K_ID		5
>>> +#define X86_XSTATE_ZMM_H_ID	6
>>> +#define X86_XSTATE_ZMM_ID	7
>>> +#define X86_XSTATE_PKRU_ID	9
>>> +
>>>   /* The extended state feature bits.  */
>>> -#define X86_XSTATE_X87		(1ULL << 0)
>>> -#define X86_XSTATE_SSE		(1ULL << 1)
>>> -#define X86_XSTATE_AVX		(1ULL << 2)
>>> -#define X86_XSTATE_BNDREGS	(1ULL << 3)
>>> -#define X86_XSTATE_BNDCFG	(1ULL << 4)
>>> +#define X86_XSTATE_X87		(1ULL << X86_XSTATE_X87_ID)
>>> +#define X86_XSTATE_SSE		(1ULL << X86_XSTATE_SSE_ID)
>>> +#define X86_XSTATE_AVX		(1ULL << X86_XSTATE_AVX_ID)
>>> +#define X86_XSTATE_BNDREGS	(1ULL << X86_XSTATE_BNDREGS_ID)
>>> +#define X86_XSTATE_BNDCFG	(1ULL << X86_XSTATE_BNDCFG_ID)
>>>   #define X86_XSTATE_MPX		(X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG)
>>>     /* AVX 512 adds three feature bits.  All three must be enabled.  */
>>> -#define X86_XSTATE_K		(1ULL << 5)
>>> -#define X86_XSTATE_ZMM_H	(1ULL << 6)
>>> -#define X86_XSTATE_ZMM		(1ULL << 7)
>>> +#define X86_XSTATE_K		(1ULL << X86_XSTATE_K_ID)
>>> +#define X86_XSTATE_ZMM_H	(1ULL << X86_XSTATE_ZMM_H_ID)
>>> +#define X86_XSTATE_ZMM		(1ULL << X86_XSTATE_ZMM_ID)
>>>   #define X86_XSTATE_AVX512	(X86_XSTATE_K | X86_XSTATE_ZMM_H \
>>>   				 | X86_XSTATE_ZMM)
>>>   -#define X86_XSTATE_PKRU		(1ULL << 9)
>>> +#define X86_XSTATE_PKRU		(1ULL << X86_XSTATE_PKRU_ID)
>>> +
>>> +/* Size and offsets of register states in the XSAVE area extended
>>> +   region.  Offsets are set to 0 to indicate the absence of the
>>> +   associated registers.  */
>> 
>> Extreme comment nitpick.  In "Size and offsets", one is singular and the
>> other is plural.  Should it be "Sizes and offsets", or "Size and
>> offset"?
>
>Ah, there's a single size and multiple offsets.  Is this version clearer:
>
>/* Total size of the XSAVE area extended region and offsets of
>   register states within the region.  Offsets are set to 0 to
>   indicate the absence of the associated registers.  */
>

Ah, sorry. The new comment is clearer, thanks. 

Simon 

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-26 22:31             ` John Baldwin
@ 2023-07-27 21:36               ` Keith Seitz
  2023-07-28 16:35                 ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Keith Seitz @ 2023-07-27 21:36 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/26/23 15:31, John Baldwin wrote:
> 
> So I have a couple of things to try here.  First, a simple fix for the crash
> is this change (relative to the branch), but it does mean the core dumps generated
> by gcore for a remote target will not contain extended XSAVE state like AVX, etc.:
> 
> diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
> index c8b467a0416..a7d61f33a08 100644
> --- a/gdb/i386-linux-tdep.c
> +++ b/gdb/i386-linux-tdep.c
> @@ -768,7 +768,7 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
> 
>     cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
> 
> -  if (tdep->xcr0 & X86_XSTATE_AVX)
> +  if (tdep->xsave_layout.sizeof_xsave != 0)
>       cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
>          tdep->xsave_layout.sizeof_xsave, &i386_linux_xstateregset,
>          "XSAVE extended state", cb_data);
> 
> Arguably that is more correct as it lines up with the way the rest of the x86 arches
> in this series.

Yeah, that does fix a lot of problems. In the vein of "perfect is the enemy of good,"
this LGTM.

> The other change I have locally is one to generate a "fallback" layout to use in
> this case that a target (such as remote) doesn't provide a layout.

> 
> The fallback change:
[snip]

This causes a new regression in gdb.base/solib-display.exp:

# make check RUNTESTFLAGS="--target_board native-extended-gdbserver.exp" \
   TESTS=gdb.base/solib-display.exp
Running /root/fsf/linux/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/solib-display.exp ...
FAIL: gdb.base/solib-display.exp: NO: continue two
FAIL: gdb.base/solib-display.exp: IN: continue two
FAIL: gdb.base/solib-display.exp: SEP: continue two

		=== gdb Summary ===

# of expected passes		32
# of unexpected failures	3

The issue is the same with all three failing tests (-m32/-m64 don't matter).
With this tweak, we now see:

warning: Unable to display "a_local": No symbol "a_local" in current context.
warning: Unable to display "a_static": No symbol "a_static" in current context.

This disables the display of the two variables, and they are omitted from
subsequent displays. [This happens on every x86_64 on which I've tested: Comet Lake,
Raptor Lake, and Sapphire Rapids.]

Keith


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-26 21:16     ` John Baldwin
@ 2023-07-27 21:48       ` Simon Marchi
  2023-07-28 16:30         ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-07-27 21:48 UTC (permalink / raw)
  To: John Baldwin, gdb-patches


> Ooo, that's a good catch.  This function is shared with amd64, so I think
> it's best if it keeps returning an xcr0 value, but we could patch
> i386_linux_core_read_description to instead do this:
> 
> static const struct target_desc *
> i386_linux_core_read_description (struct gdbarch *gdbarch,
>                   struct target_ops *target,
>                   bfd *abfd)
> {
>   /* Linux/i386.  */
>   x86_xsave_layout layout;
>   uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
>   if (xcr0 == X86_XSTATE_X87_MASK
>       && bfd_get_section_by_name (abfd, ".reg-xfp") != NULL)
>     xcr0 = X86_XSTATE_SSE_MASK;
> 
>   return i386_linux_read_description (xcr0);
> }

And i386_linux_core_read_xsave_info would return X86_XSTATE_X87_MASK if
it does not find a .reg-xstate section?

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-27 21:48       ` Simon Marchi
@ 2023-07-28 16:30         ` John Baldwin
  2023-07-28 17:58           ` Simon Marchi
  0 siblings, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-28 16:30 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 7/27/23 2:48 PM, Simon Marchi wrote:
> 
>> Ooo, that's a good catch.  This function is shared with amd64, so I think
>> it's best if it keeps returning an xcr0 value, but we could patch
>> i386_linux_core_read_description to instead do this:
>>
>> static const struct target_desc *
>> i386_linux_core_read_description (struct gdbarch *gdbarch,
>>                    struct target_ops *target,
>>                    bfd *abfd)
>> {
>>    /* Linux/i386.  */
>>    x86_xsave_layout layout;
>>    uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
>>    if (xcr0 == X86_XSTATE_X87_MASK
>>        && bfd_get_section_by_name (abfd, ".reg-xfp") != NULL)
>>      xcr0 = X86_XSTATE_SSE_MASK;
>>
>>    return i386_linux_read_description (xcr0);
>> }
> 
> And i386_linux_core_read_xsave_info would return X86_XSTATE_X87_MASK if
> it does not find a .reg-xstate section?

Hmmm.  It would need to do something like that yes.  I realize I have a
bug for i386-fbsd as well where it would return SSE when it should be
returning X87.  For amd64, both Linux and FreeBSD use FXSAVE (which
includes SSE) as .reg2 (generic FP regs).  For i386, both use FSAVE (which
only includes X87) for .reg2, and Linux/i386 also has .reg-fxp that uses
FXSAVE.  This means that the "default" xcr0 value really should be SSE
for amd64, and X87 for i386.

I was considering returning a bool from the helper methods
(i386_*_core_read_xsave_info yesterday (it makes the new gdbarch method
implementations slightly easier to read IMO).  Other options are to add a
parameter to the helper that is the "default" value of xcr0 to use, or to
return a value of 0 for xcr0 when no valid XSAVE info is found.  Returning
0 is pretty close to the bool approach without requiring a dummy xcr0 arg
in the gdbarch methods, so I think I'll go with that.

In that case, i386_linux_core_read_description would go back to what it
was in this patch, but the amd64 version would change slightly:

static const struct target_desc *
amd64_linux_core_read_description (struct gdbarch *gdbarch,
				  struct target_ops *target,
				  bfd *abfd)
{
   /* Linux/x86-64.  */
   x86_xsave_layout layout;
   uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
   if (xcr0 == 0)
     xcr0 = X86_XSTATE_SSE_MASK;

   return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
				       gdbarch_ptr_bit (gdbarch) == 32);
}

Namely to add the 'xcr == 0' case.  If that approach seems sensible I
will post a new series since it touches both this patch and the FreeBSD
one.

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 00/15] Handle variable XSAVE layouts
  2023-07-27 21:36               ` Keith Seitz
@ 2023-07-28 16:35                 ` John Baldwin
  0 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-28 16:35 UTC (permalink / raw)
  To: Keith Seitz, gdb-patches

On 7/27/23 2:36 PM, Keith Seitz wrote:
> On 7/26/23 15:31, John Baldwin wrote:
>>
>> So I have a couple of things to try here.  First, a simple fix for the crash
>> is this change (relative to the branch), but it does mean the core dumps generated
>> by gcore for a remote target will not contain extended XSAVE state like AVX, etc.:
>>
>> diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
>> index c8b467a0416..a7d61f33a08 100644
>> --- a/gdb/i386-linux-tdep.c
>> +++ b/gdb/i386-linux-tdep.c
>> @@ -768,7 +768,7 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
>>
>>      cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
>>
>> -  if (tdep->xcr0 & X86_XSTATE_AVX)
>> +  if (tdep->xsave_layout.sizeof_xsave != 0)
>>        cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
>>           tdep->xsave_layout.sizeof_xsave, &i386_linux_xstateregset,
>>           "XSAVE extended state", cb_data);
>>
>> Arguably that is more correct as it lines up with the way the rest of the x86 arches
>> in this series.
> 
> Yeah, that does fix a lot of problems. In the vein of "perfect is the enemy of good,"
> this LGTM.

Ok.

>> The other change I have locally is one to generate a "fallback" layout to use in
>> this case that a target (such as remote) doesn't provide a layout.
> 
>>
>> The fallback change:
> [snip]
> 
> This causes a new regression in gdb.base/solib-display.exp:
> 
> # make check RUNTESTFLAGS="--target_board native-extended-gdbserver.exp" \
>     TESTS=gdb.base/solib-display.exp
> Running /root/fsf/linux/gdb/testsuite/../../../src/gdb/testsuite/gdb.base/solib-display.exp ...
> FAIL: gdb.base/solib-display.exp: NO: continue two
> FAIL: gdb.base/solib-display.exp: IN: continue two
> FAIL: gdb.base/solib-display.exp: SEP: continue two
> 
> 		=== gdb Summary ===
> 
> # of expected passes		32
> # of unexpected failures	3
> 
> The issue is the same with all three failing tests (-m32/-m64 don't matter).
> With this tweak, we now see:
> 
> warning: Unable to display "a_local": No symbol "a_local" in current context.
> warning: Unable to display "a_static": No symbol "a_static" in current context.
> 
> This disables the display of the two variables, and they are omitted from
> subsequent displays. [This happens on every x86_64 on which I've tested: Comet Lake,
> Raptor Lake, and Sapphire Rapids.]

Humm, ok.  I should be able to look at this locally in a x86-64 VM I have.
I'm inclined to probably leave this off the series though for now while I
figure out the right solution to gcore of a remote process.

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-28 16:30         ` John Baldwin
@ 2023-07-28 17:58           ` Simon Marchi
  2023-07-28 21:30             ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-07-28 17:58 UTC (permalink / raw)
  To: John Baldwin, gdb-patches



On 2023-07-28 12:30, John Baldwin wrote:
> On 7/27/23 2:48 PM, Simon Marchi wrote:
>>
>>> Ooo, that's a good catch.  This function is shared with amd64, so I think
>>> it's best if it keeps returning an xcr0 value, but we could patch
>>> i386_linux_core_read_description to instead do this:
>>>
>>> static const struct target_desc *
>>> i386_linux_core_read_description (struct gdbarch *gdbarch,
>>>                    struct target_ops *target,
>>>                    bfd *abfd)
>>> {
>>>    /* Linux/i386.  */
>>>    x86_xsave_layout layout;
>>>    uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
>>>    if (xcr0 == X86_XSTATE_X87_MASK
>>>        && bfd_get_section_by_name (abfd, ".reg-xfp") != NULL)
>>>      xcr0 = X86_XSTATE_SSE_MASK;
>>>
>>>    return i386_linux_read_description (xcr0);
>>> }
>>
>> And i386_linux_core_read_xsave_info would return X86_XSTATE_X87_MASK if
>> it does not find a .reg-xstate section?
> 
> Hmmm.  It would need to do something like that yes.  I realize I have a
> bug for i386-fbsd as well where it would return SSE when it should be
> returning X87.  For amd64, both Linux and FreeBSD use FXSAVE (which
> includes SSE) as .reg2 (generic FP regs).  For i386, both use FSAVE (which
> only includes X87) for .reg2, and Linux/i386 also has .reg-fxp that uses
> FXSAVE.  This means that the "default" xcr0 value really should be SSE
> for amd64, and X87 for i386.
> 
> I was considering returning a bool from the helper methods
> (i386_*_core_read_xsave_info yesterday (it makes the new gdbarch method
> implementations slightly easier to read IMO).  Other options are to add a
> parameter to the helper that is the "default" value of xcr0 to use, or to
> return a value of 0 for xcr0 when no valid XSAVE info is found.  Returning
> 0 is pretty close to the bool approach without requiring a dummy xcr0 arg
> in the gdbarch methods, so I think I'll go with that.
> 
> In that case, i386_linux_core_read_description would go back to what it
> was in this patch, but the amd64 version would change slightly:
> 
> static const struct target_desc *
> amd64_linux_core_read_description (struct gdbarch *gdbarch,
>                   struct target_ops *target,
>                   bfd *abfd)
> {
>   /* Linux/x86-64.  */
>   x86_xsave_layout layout;
>   uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
>   if (xcr0 == 0)
>     xcr0 = X86_XSTATE_SSE_MASK;
> 
>   return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
>                        gdbarch_ptr_bit (gdbarch) == 32);
> }
> 
> Namely to add the 'xcr == 0' case.  If that approach seems sensible I
> will post a new series since it touches both this patch and the FreeBSD
> one.

I previously considered suggesting making the *_core_read_xsave_info
functions return gdb::optional<int>, where they would have returned an
empty optional if the core does not have xsave info.  The calling code
could then fall back to some other strategy.  Returning 0 achieves the
same thing in a different way, it's fine with me (as long as it's
properly documented).  I prefer that over the "passing a default value"
approach.

If the changes only touch this patch, you can send an update just for
this one (instead of the whole series).

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6a 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
  2023-07-14 15:51 ` [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts John Baldwin
  2023-07-26 20:04   ` Simon Marchi
@ 2023-07-28 21:23   ` John Baldwin
  2023-08-28 16:01     ` Simon Marchi
  1 sibling, 1 reply; 58+ messages in thread
From: John Baldwin @ 2023-07-28 21:23 UTC (permalink / raw)
  To: gdb-patches, Simon Marchi

Refactor i386fbsd_core_read_xcr0 to fetch and return a corresponding
x86_xsave_layout as well as xcr0 using the size of an existing
NT_X86_XSTATE core dump to determine the offsets via
i387_guess_xsave_layout.  Use this to add an implementation of
gdbarch_core_xfer_x86_xsave_layout.

Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
set and only fetch/store the register set if this size is non-zero.
---
  gdb/amd64-fbsd-tdep.c | 15 +++++++--
  gdb/i386-fbsd-tdep.c  | 71 ++++++++++++++++++++++++-------------------
  gdb/i386-fbsd-tdep.h  | 14 +++++++--
  3 files changed, 64 insertions(+), 36 deletions(-)

diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c
index 0d5ce004fb1..2b633cd479c 100644
--- a/gdb/amd64-fbsd-tdep.c
+++ b/gdb/amd64-fbsd-tdep.c
@@ -224,7 +224,12 @@ amd64fbsd_core_read_description (struct gdbarch *gdbarch,
  				 struct target_ops *target,
  				 bfd *abfd)
  {
-  return amd64_target_description (i386fbsd_core_read_xcr0 (abfd), true);
+  x86_xsave_layout layout;
+  uint64_t xcr0 = i386_fbsd_core_read_xsave_info (abfd, layout);
+  if (xcr0 == 0)
+    xcr0 = X86_XSTATE_SSE_MASK;
+
+  return amd64_target_description (xcr0, true);
  }
  
  /* Similar to amd64_supply_fpregset, but use XSAVE extended state.  */
@@ -271,8 +276,10 @@ amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
    cb (".reg-x86-segbases", AMD64_FBSD_SIZEOF_SEGBASES_REGSET,
        AMD64_FBSD_SIZEOF_SEGBASES_REGSET, &amd64_fbsd_segbases_regset,
        "segment bases", cb_data);
-  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
-      &amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
+  if (tdep->xsave_layout.sizeof_xsave != 0)
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &amd64fbsd_xstateregset,
+	"XSAVE extended state", cb_data);
  }
  
  /* Implement the get_thread_local_address gdbarch method.  */
@@ -313,6 +320,8 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    tramp_frame_prepend_unwinder (gdbarch, &amd64_fbsd_sigframe);
  
    tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_fbsd_core_read_x86_xsave_layout);
  
    /* Iterate over core file register note sections.  */
    set_gdbarch_iterate_over_regset_sections
diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c
index fb9030413ab..f8c2758c2b0 100644
--- a/gdb/i386-fbsd-tdep.c
+++ b/gdb/i386-fbsd-tdep.c
@@ -18,13 +18,13 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
  
  #include "defs.h"
+#include "gdbcore.h"
  #include "osabi.h"
  #include "regcache.h"
  #include "regset.h"
  #include "trad-frame.h"
  #include "tramp-frame.h"
  #include "i386-fbsd-tdep.h"
-#include "gdbsupport/x86-xstate.h"
  
  #include "i386-tdep.h"
  #include "i387-tdep.h"
@@ -241,43 +241,46 @@ static const struct tramp_frame i386_fbsd64_sigframe =
    i386_fbsd_sigframe_init
  };
  
-/* Get XSAVE extended state xcr0 from core dump.  */
+/* See i386-fbsd-tdep.h.  */
  
  uint64_t
-i386fbsd_core_read_xcr0 (bfd *abfd)
+i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
  {
    asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
-  uint64_t xcr0;
+  if (xstate == nullptr)
+    return 0;
  
-  if (xstate)
+  /* Check extended state size.  */
+  size_t size = bfd_section_size (xstate);
+  if (size < X86_XSTATE_AVX_SIZE)
+    return 0;
+
+  char contents[8];
+  if (! bfd_get_section_contents (abfd, xstate, contents,
+				  I386_FBSD_XSAVE_XCR0_OFFSET, 8))
      {
-      size_t size = bfd_section_size (xstate);
-
-      /* Check extended state size.  */
-      if (size < X86_XSTATE_AVX_SIZE)
-	xcr0 = X86_XSTATE_SSE_MASK;
-      else
-	{
-	  char contents[8];
-
-	  if (! bfd_get_section_contents (abfd, xstate, contents,
-					  I386_FBSD_XSAVE_XCR0_OFFSET,
-					  8))
-	    {
-	      warning (_("Couldn't read `xcr0' bytes from "
-			 "`.reg-xstate' section in core file."));
-	      return X86_XSTATE_SSE_MASK;
-	    }
-
-	  xcr0 = bfd_get_64 (abfd, contents);
-	}
+      warning (_("Couldn't read `xcr0' bytes from "
+		 "`.reg-xstate' section in core file."));
+      return 0;
      }
-  else
-    xcr0 = X86_XSTATE_SSE_MASK;
+
+  uint64_t xcr0 = bfd_get_64 (abfd, contents);
+
+  if (!i387_guess_xsave_layout (xcr0, size, layout))
+    return 0;
  
    return xcr0;
  }
  
+/* See i386-fbsd-tdep.h.  */
+
+bool
+i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+				      x86_xsave_layout &layout)
+{
+  return i386_fbsd_core_read_xsave_info (core_bfd, layout) != 0;
+}
+
  /* Implement the core_read_description gdbarch method.  */
  
  static const struct target_desc *
@@ -285,7 +288,11 @@ i386fbsd_core_read_description (struct gdbarch *gdbarch,
  				struct target_ops *target,
  				bfd *abfd)
  {
-  return i386_target_description (i386fbsd_core_read_xcr0 (abfd), true);
+  x86_xsave_layout layout;
+  uint64_t xcr0 = i386_fbsd_core_read_xsave_info (abfd, layout);
+  if (xcr0 == 0)
+    xcr0 = X86_XSTATE_X87_MASK;
+  return i386_target_description (xcr0, true);
  }
  
  /* Similar to i386_supply_fpregset, but use XSAVE extended state.  */
@@ -335,9 +342,9 @@ i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
        I386_FBSD_SIZEOF_SEGBASES_REGSET, &i386_fbsd_segbases_regset,
        "segment bases", cb_data);
  
-  if (tdep->xcr0 & X86_XSTATE_AVX)
-    cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
-	X86_XSTATE_SIZE (tdep->xcr0), &i386fbsd_xstateregset,
+  if (tdep->xsave_layout.sizeof_xsave != 0)
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &i386fbsd_xstateregset,
  	"XSAVE extended state", cb_data);
  }
  
@@ -386,6 +393,8 @@ i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    i386_elf_init_abi (info, gdbarch);
  
    tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_fbsd_core_read_x86_xsave_layout);
  
    /* Iterate over core file register note sections.  */
    set_gdbarch_iterate_over_regset_sections
diff --git a/gdb/i386-fbsd-tdep.h b/gdb/i386-fbsd-tdep.h
index cb991af9e49..c49cb1eba68 100644
--- a/gdb/i386-fbsd-tdep.h
+++ b/gdb/i386-fbsd-tdep.h
@@ -20,10 +20,20 @@
  #ifndef I386_FBSD_TDEP_H
  #define I386_FBSD_TDEP_H
  
+#include "gdbsupport/x86-xstate.h"
  #include "regset.h"
  
-/* Get XSAVE extended state xcr0 from core dump.  */
-extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd);
+/* Read the XSAVE extended state xcr0 value from the ABFD core file.
+   If it appears to be valid, return it and fill LAYOUT with values
+   inferred from that value.
+
+   Otherwise, return 0 to indicate no state was found and leave LAYOUT
+   untouched.  */
+uint64_t i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout);
+
+/* Implement the core_read_x86_xsave_layout gdbarch method.  */
+bool i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+					   x86_xsave_layout &layout);
  
  /* The format of the XSAVE extended area is determined by hardware.
     Cores store the XSAVE extended area in a NT_X86_XSTATE note that
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v6a 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-14 15:51 ` [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts John Baldwin
  2023-07-26 20:45   ` Simon Marchi
@ 2023-07-28 21:29   ` John Baldwin
  2023-08-14 17:52     ` John Baldwin
  2023-08-28 16:21     ` Simon Marchi
  1 sibling, 2 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-28 21:29 UTC (permalink / raw)
  To: gdb-patches, Simon Marchi

Refactor i386_linux_core_read_xcr0 to fetch and return a corresponding
x86_xsave_layout as well as xcr0 using the size of an existing
NT_X86_XSTATE core dump to determine the offsets via
i387_guess_xsave_layout.  Use this to add an implementation of
gdbarch_core_xfer_x86_xsave_layout.

Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
set.
---
  gdb/amd64-linux-tdep.c | 13 +++++++--
  gdb/i386-linux-tdep.c  | 66 +++++++++++++++++++++++-------------------
  gdb/i386-linux-tdep.h  | 25 +++++++++-------
  3 files changed, 61 insertions(+), 43 deletions(-)

diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index cbbac1a0c64..e2fdf5fb6c8 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1616,7 +1616,10 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
  				  bfd *abfd)
  {
    /* Linux/x86-64.  */
-  uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
+  x86_xsave_layout layout;
+  uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
+  if (xcr0 == 0)
+    xcr0 = X86_XSTATE_SSE_MASK;
  
    return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
  				       gdbarch_ptr_bit (gdbarch) == 32);
@@ -1661,8 +1664,10 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
  
    cb (".reg", 27 * 8, 27 * 8, &i386_gregset, NULL, cb_data);
    cb (".reg2", 512, 512, &amd64_fpregset, NULL, cb_data);
-  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
-      &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
+  if (tdep->xsave_layout.sizeof_xsave != 0)
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &amd64_linux_xstateregset,
+	"XSAVE extended state", cb_data);
  }
  
  /* The instruction sequences used in x86_64 machines for a
@@ -1804,6 +1809,8 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
    tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset);
  
    tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_linux_core_read_x86_xsave_layout);
  
    /* Add the %orig_rax register used for syscall restarting.  */
    set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc);
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 554c1455a5f..7ff7c155e2c 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -638,45 +638,48 @@ static int i386_linux_sc_reg_offset[] =
    0 * 4				/* %gs */
  };
  
-/* Get XSAVE extended state xcr0 from core dump.  */
+/* See i386-linux-tdep.h.  */
  
  uint64_t
-i386_linux_core_read_xcr0 (bfd *abfd)
+i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
  {
    asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
-  uint64_t xcr0;
+  if (xstate == nullptr)
+    return 0;
  
-  if (xstate)
+  /* Check extended state size.  */
+  size_t size = bfd_section_size (xstate);
+  if (size < X86_XSTATE_AVX_SIZE)
+    return 0;
+
+  char contents[8];
+  if (! bfd_get_section_contents (abfd, xstate, contents,
+				  I386_LINUX_XSAVE_XCR0_OFFSET, 8))
      {
-      size_t size = bfd_section_size (xstate);
-
-      /* Check extended state size.  */
-      if (size < X86_XSTATE_AVX_SIZE)
-	xcr0 = X86_XSTATE_SSE_MASK;
-      else
-	{
-	  char contents[8];
-
-	  if (! bfd_get_section_contents (abfd, xstate, contents,
-					  I386_LINUX_XSAVE_XCR0_OFFSET,
-					  8))
-	    {
-	      warning (_("Couldn't read `xcr0' bytes from "
-			 "`.reg-xstate' section in core file."));
-	      return 0;
-	    }
-
-	  xcr0 = bfd_get_64 (abfd, contents);
-	}
+      warning (_("Couldn't read `xcr0' bytes from "
+		 "`.reg-xstate' section in core file."));
+      return 0;
      }
-  else
-    xcr0 = 0;
+
+  uint64_t xcr0 = bfd_get_64 (abfd, contents);
+
+  if (!i387_guess_xsave_layout (xcr0, size, layout))
+    return 0;
  
    return xcr0;
  }
  
  /* See i386-linux-tdep.h.  */
  
+bool
+i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+				       x86_xsave_layout &layout)
+{
+  return i386_linux_core_read_xsave_info (core_bfd, layout) != 0;
+}
+
+/* See i386-linux-tdep.h.  */
+
  const struct target_desc *
  i386_linux_read_description (uint64_t xcr0)
  {
@@ -708,7 +711,8 @@ i386_linux_core_read_description (struct gdbarch *gdbarch,
  				  bfd *abfd)
  {
    /* Linux/i386.  */
-  uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
+  x86_xsave_layout layout;
+  uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
    const struct target_desc *tdesc = i386_linux_read_description (xcr0);
  
    if (tdesc != NULL)
@@ -767,9 +771,9 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
  
    cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
  
-  if (tdep->xcr0 & X86_XSTATE_AVX)
-    cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
-	X86_XSTATE_SIZE (tdep->xcr0), &i386_linux_xstateregset,
+  if (tdep->xsave_layout.sizeof_xsave != 0)
+    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
+	tdep->xsave_layout.sizeof_xsave, &i386_linux_xstateregset,
  	"XSAVE extended state", cb_data);
    else if (tdep->xcr0 & X86_XSTATE_SSE)
      cb (".reg-xfp", 512, 512, &i386_fpregset, "extended floating-point",
@@ -872,6 +876,8 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
  
    tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
+  set_gdbarch_core_read_x86_xsave_layout
+    (gdbarch, i386_linux_core_read_x86_xsave_layout);
  
    set_gdbarch_process_record (gdbarch, i386_process_record);
    set_gdbarch_process_record_signal (gdbarch, i386_linux_record_signal);
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index c0fd1f7f300..bd8e328b7fe 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -20,6 +20,8 @@
  #ifndef I386_LINUX_TDEP_H
  #define I386_LINUX_TDEP_H
  
+#include "gdbsupport/x86-xstate.h"
+
  /* The Linux kernel pretends there is an additional "orig_eax"
     register.  Since GDB needs access to that register to be able to
     properly restart system calls when necessary (see
@@ -34,8 +36,18 @@
  /* Total number of registers for GNU/Linux.  */
  #define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1)
  
-/* Get XSAVE extended state xcr0 from core dump.  */
-extern uint64_t i386_linux_core_read_xcr0 (bfd *abfd);
+/* Read the XSAVE extended state xcr0 value from the ABFD core file.
+   If it appears to be valid, return it and fill LAYOUT with values
+   inferred from that value.
+
+   Otherwise, return 0 to indicate no state was found and leave LAYOUT
+   untouched.  */
+extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
+						 x86_xsave_layout &layout);
+
+/* Implement the core_read_x86_xsave_layout gdbarch method.  */
+extern bool i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
+						   x86_xsave_layout &layout);
  
  /* Handle and display information related to the MPX bound violation
     to the user.  */
@@ -52,14 +64,7 @@ extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
  	  fxsave_bytes[0..463]
  	  sw_usable_bytes[464..511]
  	  xstate_hdr_bytes[512..575]
-	  avx_bytes[576..831]
-	  mpx_bytes [960..1032]
-	  avx512_k_regs[1088..1152]
-	  avx512_zmmh_regs0-7[1153..1407]
-	  avx512_zmmh_regs8-15[1408..1663]
-	  avx512_zmm_regs16-31[1664..2687]
-	  pkru[2688..2752]
-	  future_state etc
+	  extended state regions (AVX, MPX, AVX512, PKRU, etc.)
  	};
  
    Same memory layout will be used for the coredump NT_X86_XSTATE
-- 
2.40.0


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-28 17:58           ` Simon Marchi
@ 2023-07-28 21:30             ` John Baldwin
  0 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-07-28 21:30 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 7/28/23 10:58 AM, Simon Marchi wrote:
> On 2023-07-28 12:30, John Baldwin wrote:
>> On 7/27/23 2:48 PM, Simon Marchi wrote:
>>>
>>>> Ooo, that's a good catch.  This function is shared with amd64, so I think
>>>> it's best if it keeps returning an xcr0 value, but we could patch
>>>> i386_linux_core_read_description to instead do this:
>>>>
>>>> static const struct target_desc *
>>>> i386_linux_core_read_description (struct gdbarch *gdbarch,
>>>>                     struct target_ops *target,
>>>>                     bfd *abfd)
>>>> {
>>>>     /* Linux/i386.  */
>>>>     x86_xsave_layout layout;
>>>>     uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
>>>>     if (xcr0 == X86_XSTATE_X87_MASK
>>>>         && bfd_get_section_by_name (abfd, ".reg-xfp") != NULL)
>>>>       xcr0 = X86_XSTATE_SSE_MASK;
>>>>
>>>>     return i386_linux_read_description (xcr0);
>>>> }
>>>
>>> And i386_linux_core_read_xsave_info would return X86_XSTATE_X87_MASK if
>>> it does not find a .reg-xstate section?
>>
>> Hmmm.  It would need to do something like that yes.  I realize I have a
>> bug for i386-fbsd as well where it would return SSE when it should be
>> returning X87.  For amd64, both Linux and FreeBSD use FXSAVE (which
>> includes SSE) as .reg2 (generic FP regs).  For i386, both use FSAVE (which
>> only includes X87) for .reg2, and Linux/i386 also has .reg-fxp that uses
>> FXSAVE.  This means that the "default" xcr0 value really should be SSE
>> for amd64, and X87 for i386.
>>
>> I was considering returning a bool from the helper methods
>> (i386_*_core_read_xsave_info yesterday (it makes the new gdbarch method
>> implementations slightly easier to read IMO).  Other options are to add a
>> parameter to the helper that is the "default" value of xcr0 to use, or to
>> return a value of 0 for xcr0 when no valid XSAVE info is found.  Returning
>> 0 is pretty close to the bool approach without requiring a dummy xcr0 arg
>> in the gdbarch methods, so I think I'll go with that.
>>
>> In that case, i386_linux_core_read_description would go back to what it
>> was in this patch, but the amd64 version would change slightly:
>>
>> static const struct target_desc *
>> amd64_linux_core_read_description (struct gdbarch *gdbarch,
>>                    struct target_ops *target,
>>                    bfd *abfd)
>> {
>>    /* Linux/x86-64.  */
>>    x86_xsave_layout layout;
>>    uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
>>    if (xcr0 == 0)
>>      xcr0 = X86_XSTATE_SSE_MASK;
>>
>>    return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
>>                         gdbarch_ptr_bit (gdbarch) == 32);
>> }
>>
>> Namely to add the 'xcr == 0' case.  If that approach seems sensible I
>> will post a new series since it touches both this patch and the FreeBSD
>> one.
> 
> I previously considered suggesting making the *_core_read_xsave_info
> functions return gdb::optional<int>, where they would have returned an
> empty optional if the core does not have xsave info.  The calling code
> could then fall back to some other strategy.  Returning 0 achieves the
> same thing in a different way, it's fine with me (as long as it's
> properly documented).  I prefer that over the "passing a default value"
> approach.
> 
> If the changes only touch this patch, you can send an update just for
> this one (instead of the whole series).

It touches both this one and the similar FreeBSD one, so I've sent both.
This patch (patch 8) also now contains one extra change from Keith's
testing (testing sizeof_xsave != 0 to control use of .reg-xstate for
i386)

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6a 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-28 21:29   ` [PATCH v6a " John Baldwin
@ 2023-08-14 17:52     ` John Baldwin
  2023-08-28 16:21     ` Simon Marchi
  1 sibling, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-08-14 17:52 UTC (permalink / raw)
  To: gdb-patches, Simon Marchi

On 7/28/23 2:29 PM, John Baldwin wrote:
> Refactor i386_linux_core_read_xcr0 to fetch and return a corresponding
> x86_xsave_layout as well as xcr0 using the size of an existing
> NT_X86_XSTATE core dump to determine the offsets via
> i387_guess_xsave_layout.  Use this to add an implementation of
> gdbarch_core_xfer_x86_xsave_layout.
> 
> Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
> set.
> ---
>    gdb/amd64-linux-tdep.c | 13 +++++++--
>    gdb/i386-linux-tdep.c  | 66 +++++++++++++++++++++++-------------------
>    gdb/i386-linux-tdep.h  | 25 +++++++++-------
>    3 files changed, 61 insertions(+), 43 deletions(-)
> 
> diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
> index cbbac1a0c64..e2fdf5fb6c8 100644
> --- a/gdb/amd64-linux-tdep.c
> +++ b/gdb/amd64-linux-tdep.c
> @@ -1616,7 +1616,10 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
>    				  bfd *abfd)
>    {
>      /* Linux/x86-64.  */
> -  uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
> +  x86_xsave_layout layout;
> +  uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
> +  if (xcr0 == 0)
> +    xcr0 = X86_XSTATE_SSE_MASK;
>    
>      return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
>    				       gdbarch_ptr_bit (gdbarch) == 32);
> @@ -1661,8 +1664,10 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
>    
>      cb (".reg", 27 * 8, 27 * 8, &i386_gregset, NULL, cb_data);
>      cb (".reg2", 512, 512, &amd64_fpregset, NULL, cb_data);
> -  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
> -      &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
> +  if (tdep->xsave_layout.sizeof_xsave != 0)
> +    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
> +	tdep->xsave_layout.sizeof_xsave, &amd64_linux_xstateregset,
> +	"XSAVE extended state", cb_data);
>    }
>    
>    /* The instruction sequences used in x86_64 machines for a
> @@ -1804,6 +1809,8 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
>      tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset);
>    
>      tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
> +  set_gdbarch_core_read_x86_xsave_layout
> +    (gdbarch, i386_linux_core_read_x86_xsave_layout);
>    
>      /* Add the %orig_rax register used for syscall restarting.  */
>      set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc);
> diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
> index 554c1455a5f..7ff7c155e2c 100644
> --- a/gdb/i386-linux-tdep.c
> +++ b/gdb/i386-linux-tdep.c
> @@ -638,45 +638,48 @@ static int i386_linux_sc_reg_offset[] =
>      0 * 4				/* %gs */
>    };
>    
> -/* Get XSAVE extended state xcr0 from core dump.  */
> +/* See i386-linux-tdep.h.  */
>    
>    uint64_t
> -i386_linux_core_read_xcr0 (bfd *abfd)
> +i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
>    {
>      asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
> -  uint64_t xcr0;
> +  if (xstate == nullptr)
> +    return 0;
>    
> -  if (xstate)
> +  /* Check extended state size.  */
> +  size_t size = bfd_section_size (xstate);
> +  if (size < X86_XSTATE_AVX_SIZE)
> +    return 0;
> +
> +  char contents[8];
> +  if (! bfd_get_section_contents (abfd, xstate, contents,
> +				  I386_LINUX_XSAVE_XCR0_OFFSET, 8))
>        {
> -      size_t size = bfd_section_size (xstate);
> -
> -      /* Check extended state size.  */
> -      if (size < X86_XSTATE_AVX_SIZE)
> -	xcr0 = X86_XSTATE_SSE_MASK;
> -      else
> -	{
> -	  char contents[8];
> -
> -	  if (! bfd_get_section_contents (abfd, xstate, contents,
> -					  I386_LINUX_XSAVE_XCR0_OFFSET,
> -					  8))
> -	    {
> -	      warning (_("Couldn't read `xcr0' bytes from "
> -			 "`.reg-xstate' section in core file."));
> -	      return 0;
> -	    }
> -
> -	  xcr0 = bfd_get_64 (abfd, contents);
> -	}
> +      warning (_("Couldn't read `xcr0' bytes from "
> +		 "`.reg-xstate' section in core file."));
> +      return 0;
>        }
> -  else
> -    xcr0 = 0;
> +
> +  uint64_t xcr0 = bfd_get_64 (abfd, contents);
> +
> +  if (!i387_guess_xsave_layout (xcr0, size, layout))
> +    return 0;
>    
>      return xcr0;
>    }
>    
>    /* See i386-linux-tdep.h.  */
>    
> +bool
> +i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
> +				       x86_xsave_layout &layout)
> +{
> +  return i386_linux_core_read_xsave_info (core_bfd, layout) != 0;
> +}
> +
> +/* See i386-linux-tdep.h.  */
> +
>    const struct target_desc *
>    i386_linux_read_description (uint64_t xcr0)
>    {
> @@ -708,7 +711,8 @@ i386_linux_core_read_description (struct gdbarch *gdbarch,
>    				  bfd *abfd)
>    {
>      /* Linux/i386.  */
> -  uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
> +  x86_xsave_layout layout;
> +  uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
>      const struct target_desc *tdesc = i386_linux_read_description (xcr0);
>    
>      if (tdesc != NULL)
> @@ -767,9 +771,9 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
>    
>      cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
>    
> -  if (tdep->xcr0 & X86_XSTATE_AVX)
> -    cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
> -	X86_XSTATE_SIZE (tdep->xcr0), &i386_linux_xstateregset,
> +  if (tdep->xsave_layout.sizeof_xsave != 0)
> +    cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
> +	tdep->xsave_layout.sizeof_xsave, &i386_linux_xstateregset,
>    	"XSAVE extended state", cb_data);
>      else if (tdep->xcr0 & X86_XSTATE_SSE)
>        cb (".reg-xfp", 512, 512, &i386_fpregset, "extended floating-point",
> @@ -872,6 +876,8 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>      tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
>    
>      tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
> +  set_gdbarch_core_read_x86_xsave_layout
> +    (gdbarch, i386_linux_core_read_x86_xsave_layout);
>    
>      set_gdbarch_process_record (gdbarch, i386_process_record);
>      set_gdbarch_process_record_signal (gdbarch, i386_linux_record_signal);
> diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
> index c0fd1f7f300..bd8e328b7fe 100644
> --- a/gdb/i386-linux-tdep.h
> +++ b/gdb/i386-linux-tdep.h
> @@ -20,6 +20,8 @@
>    #ifndef I386_LINUX_TDEP_H
>    #define I386_LINUX_TDEP_H
>    
> +#include "gdbsupport/x86-xstate.h"
> +
>    /* The Linux kernel pretends there is an additional "orig_eax"
>       register.  Since GDB needs access to that register to be able to
>       properly restart system calls when necessary (see
> @@ -34,8 +36,18 @@
>    /* Total number of registers for GNU/Linux.  */
>    #define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1)
>    
> -/* Get XSAVE extended state xcr0 from core dump.  */
> -extern uint64_t i386_linux_core_read_xcr0 (bfd *abfd);
> +/* Read the XSAVE extended state xcr0 value from the ABFD core file.
> +   If it appears to be valid, return it and fill LAYOUT with values
> +   inferred from that value.
> +
> +   Otherwise, return 0 to indicate no state was found and leave LAYOUT
> +   untouched.  */
> +extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
> +						 x86_xsave_layout &layout);
> +
> +/* Implement the core_read_x86_xsave_layout gdbarch method.  */
> +extern bool i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
> +						   x86_xsave_layout &layout);
>    
>    /* Handle and display information related to the MPX bound violation
>       to the user.  */
> @@ -52,14 +64,7 @@ extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
>    	  fxsave_bytes[0..463]
>    	  sw_usable_bytes[464..511]
>    	  xstate_hdr_bytes[512..575]
> -	  avx_bytes[576..831]
> -	  mpx_bytes [960..1032]
> -	  avx512_k_regs[1088..1152]
> -	  avx512_zmmh_regs0-7[1153..1407]
> -	  avx512_zmmh_regs8-15[1408..1663]
> -	  avx512_zmm_regs16-31[1664..2687]
> -	  pkru[2688..2752]
> -	  future_state etc
> +	  extended state regions (AVX, MPX, AVX512, PKRU, etc.)
>    	};
>    
>      Same memory layout will be used for the coredump NT_X86_XSTATE

Ping?

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6a 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts.
  2023-07-28 21:23   ` [PATCH v6a " John Baldwin
@ 2023-08-28 16:01     ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 16:01 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/28/23 17:23, John Baldwin wrote:
> Refactor i386fbsd_core_read_xcr0 to fetch and return a corresponding
> x86_xsave_layout as well as xcr0 using the size of an existing
> NT_X86_XSTATE core dump to determine the offsets via
> i387_guess_xsave_layout.  Use this to add an implementation of
> gdbarch_core_xfer_x86_xsave_layout.
> 
> Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
> set and only fetch/store the register set if this size is non-zero.

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6a 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts.
  2023-07-28 21:29   ` [PATCH v6a " John Baldwin
  2023-08-14 17:52     ` John Baldwin
@ 2023-08-28 16:21     ` Simon Marchi
  1 sibling, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 16:21 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/28/23 17:29, John Baldwin wrote:
> Refactor i386_linux_core_read_xcr0 to fetch and return a corresponding
> x86_xsave_layout as well as xcr0 using the size of an existing
> NT_X86_XSTATE core dump to determine the offsets via
> i387_guess_xsave_layout.  Use this to add an implementation of
> gdbarch_core_xfer_x86_xsave_layout.
> 
> Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
> set.

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 10/15] gdb: Use x86_xstate_layout to parse the XSAVE extended state area.
  2023-07-14 15:51 ` [PATCH v6 10/15] gdb: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
@ 2023-08-28 16:34   ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 16:34 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> All of the tables describing the offsets of individual registers for
> XSAVE state components now hold relative offsets rather than absolute
> offsets.  Some tables (those for MPX registers and ZMMH registers) had
> to be split into separate tables as they held entries that spanned
> multiple state components.

I've looked at that patch previously, I'm not sure I'd be able to spot
a mistake in there.  Hopefully the testsuite coverage is good enough!

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 11/15] gdbserver: Add a function to set the XSAVE mask and size.
  2023-07-14 15:51 ` [PATCH v6 11/15] gdbserver: Add a function to set the XSAVE mask and size John Baldwin
@ 2023-08-28 16:46   ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 16:46 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> Make x86_xcr0 private to i387-fp.cc and use i387_set_xsave_mask to set
> the value instead.  Add a static global instance of x86_xsave_layout
> and initialize it in the new function as well to be used in a future
> commit to parse XSAVE extended state regions.
> 
> Update the Linux port to use this function rather than setting
> x86_xcr0 directly.  In the case that XML is not supported, don't
> bother setting x86_xcr0 to the default value but just omit the call to
> i387_set_xsave_mask as i387-fp.cc defaults to the SSE case used for
> non-XML.
> 
> In addition, use x86_xsave_length to determine the size of the XSAVE
> register set via CPUID.

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 12/15] gdbserver: Refactor the legacy region within the xsave struct
  2023-07-14 15:51 ` [PATCH v6 12/15] gdbserver: Refactor the legacy region within the xsave struct John Baldwin
@ 2023-08-28 16:50   ` Simon Marchi
  2023-08-28 17:32     ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 16:50 UTC (permalink / raw)
  To: John Baldwin, gdb-patches; +Cc: Aleksandar Paunovic

On 7/14/23 11:51, John Baldwin wrote:
> From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
> 
> Legacy fields of the XSAVE area are already defined within fx_save
> struct.  Use class inheritance to remove code duplication.
> 
> The two changed functions are called within all tests which run
> gdbserver.
> 
> Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
> Co-authored-by: John Baldwin <jhb@FreeBSD.org>
> ---
>  gdbserver/i387-fp.cc | 27 ++-------------------------
>  1 file changed, 2 insertions(+), 25 deletions(-)
> 
> diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
> index b8d7a912f26..a122e2d860b 100644
> --- a/gdbserver/i387-fp.cc
> +++ b/gdbserver/i387-fp.cc
> @@ -81,29 +81,7 @@ struct i387_fxsave {
>    unsigned char xmm_space[256];
>  };
>  
> -struct i387_xsave {
> -  /* All these are only sixteen bits, plus padding, except for fop (which
> -     is only eleven bits), and fooff / fioff (which are 32 bits each).  */
> -  unsigned short fctrl;
> -  unsigned short fstat;
> -  unsigned short ftag;
> -  unsigned short fop;
> -  unsigned int fioff;
> -  unsigned short fiseg;
> -  unsigned short pad1;
> -  unsigned int fooff;
> -  unsigned short foseg;
> -  unsigned short pad12;
> -
> -  unsigned int mxcsr;
> -  unsigned int mxcsr_mask;
> -
> -  /* Space for eight 80-bit FP values in 128-bit spaces.  */
> -  unsigned char st_space[128];
> -
> -  /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
> -  unsigned char xmm_space[256];
> -
> +struct i387_xsave : public i387_fxsave {


The { should go on the next line... can you fix all the structs in this
file with an obvious patch on top of the series?

Otherwise:

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 12/15] gdbserver: Refactor the legacy region within the xsave struct
  2023-08-28 16:50   ` Simon Marchi
@ 2023-08-28 17:32     ` John Baldwin
  0 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-08-28 17:32 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches; +Cc: Aleksandar Paunovic

On 8/28/23 9:50 AM, Simon Marchi wrote:
> On 7/14/23 11:51, John Baldwin wrote:
>> From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
>>
>> Legacy fields of the XSAVE area are already defined within fx_save
>> struct.  Use class inheritance to remove code duplication.
>>
>> The two changed functions are called within all tests which run
>> gdbserver.
>>
>> Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
>> Co-authored-by: John Baldwin <jhb@FreeBSD.org>
>> ---
>>   gdbserver/i387-fp.cc | 27 ++-------------------------
>>   1 file changed, 2 insertions(+), 25 deletions(-)
>>
>> diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
>> index b8d7a912f26..a122e2d860b 100644
>> --- a/gdbserver/i387-fp.cc
>> +++ b/gdbserver/i387-fp.cc
>> @@ -81,29 +81,7 @@ struct i387_fxsave {
>>     unsigned char xmm_space[256];
>>   };
>>   
>> -struct i387_xsave {
>> -  /* All these are only sixteen bits, plus padding, except for fop (which
>> -     is only eleven bits), and fooff / fioff (which are 32 bits each).  */
>> -  unsigned short fctrl;
>> -  unsigned short fstat;
>> -  unsigned short ftag;
>> -  unsigned short fop;
>> -  unsigned int fioff;
>> -  unsigned short fiseg;
>> -  unsigned short pad1;
>> -  unsigned int fooff;
>> -  unsigned short foseg;
>> -  unsigned short pad12;
>> -
>> -  unsigned int mxcsr;
>> -  unsigned int mxcsr_mask;
>> -
>> -  /* Space for eight 80-bit FP values in 128-bit spaces.  */
>> -  unsigned char st_space[128];
>> -
>> -  /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
>> -  unsigned char xmm_space[256];
>> -
>> +struct i387_xsave : public i387_fxsave {
> 
> 
> The { should go on the next line... can you fix all the structs in this
> file with an obvious patch on top of the series?

Will do, thanks!

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 13/15] gdbserver: Use x86_xstate_layout to parse the XSAVE extended state area.
  2023-07-14 15:51 ` [PATCH v6 13/15] gdbserver: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
@ 2023-08-28 18:15   ` Simon Marchi
  2023-08-28 18:37     ` John Baldwin
  0 siblings, 1 reply; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 18:15 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
> 
> Replace the extended state area fields of i387_xsave with methods which
> return an offset into the XSAVE buffer.
> 
> The two changed functions are called within all tests which runs
> gdbserver.
> 
> Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
> Co-authored-by: John Baldwin <jhb@FreeBSD.org>
> ---
>  gdbserver/i387-fp.cc | 117 +++++++++++++++++++++++++------------------
>  1 file changed, 69 insertions(+), 48 deletions(-)
> 
> diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
> index a122e2d860b..f53a6cfc477 100644
> --- a/gdbserver/i387-fp.cc
> +++ b/gdbserver/i387-fp.cc
> @@ -82,6 +82,8 @@ struct i387_fxsave {
>  };
>  
>  struct i387_xsave : public i387_fxsave {
> +  /* Size of i387_fxsave is 416 bytes.  */

Add a gdb_static_assert to make sure of that?

> +  /* Memory address of 16 512-bit zmm16-31 values.  */
> +  unsigned char *zmm_space ()
> +  { return xsave () + xsave_layout.zmm_offset; }

Since this doesn't Would it be clearer to call this field (and method) zmm16_offset
(zmm16_space), to make it clear that it's the space for the zmm
registers starting at 16?

In any case:

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 13/15] gdbserver: Use x86_xstate_layout to parse the XSAVE extended state area.
  2023-08-28 18:15   ` Simon Marchi
@ 2023-08-28 18:37     ` John Baldwin
  0 siblings, 0 replies; 58+ messages in thread
From: John Baldwin @ 2023-08-28 18:37 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 8/28/23 11:15 AM, Simon Marchi wrote:
> On 7/14/23 11:51, John Baldwin wrote:
>> From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
>>
>> Replace the extended state area fields of i387_xsave with methods which
>> return an offset into the XSAVE buffer.
>>
>> The two changed functions are called within all tests which runs
>> gdbserver.
>>
>> Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
>> Co-authored-by: John Baldwin <jhb@FreeBSD.org>
>> ---
>>   gdbserver/i387-fp.cc | 117 +++++++++++++++++++++++++------------------
>>   1 file changed, 69 insertions(+), 48 deletions(-)
>>
>> diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
>> index a122e2d860b..f53a6cfc477 100644
>> --- a/gdbserver/i387-fp.cc
>> +++ b/gdbserver/i387-fp.cc
>> @@ -82,6 +82,8 @@ struct i387_fxsave {
>>   };
>>   
>>   struct i387_xsave : public i387_fxsave {
>> +  /* Size of i387_fxsave is 416 bytes.  */
> 
> Add a gdb_static_assert to make sure of that?

Yes, I can add that.  I thought of that when re-reading the patch today myself.

>> +  /* Memory address of 16 512-bit zmm16-31 values.  */
>> +  unsigned char *zmm_space ()
>> +  { return xsave () + xsave_layout.zmm_offset; }
> 
> Since this doesn't Would it be clearer to call this field (and method) zmm16_offset
> (zmm16_space), to make it clear that it's the space for the zmm
> registers starting at 16?

Oh, yeah, that's a good suggestion.

> In any case:
> 
> Approved-By: Simon Marchi <simon.marchi@efficios.com>
> 
> Simon

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 14/15] x86: Remove X86_XSTATE_SIZE and related constants.
  2023-07-14 15:51 ` [PATCH v6 14/15] x86: Remove X86_XSTATE_SIZE and related constants John Baldwin
@ 2023-08-28 20:38   ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 20:38 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> ---
>  gdbsupport/x86-xstate.h | 12 ------------
>  1 file changed, 12 deletions(-)
> 
> diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
> index 27fc0bd12f2..40963bda55b 100644
> --- a/gdbsupport/x86-xstate.h
> +++ b/gdbsupport/x86-xstate.h
> @@ -99,11 +99,6 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
>  
>  #define X86_XSTATE_SSE_SIZE	576
>  #define X86_XSTATE_AVX_SIZE	832
> -#define X86_XSTATE_BNDREGS_SIZE	1024
> -#define X86_XSTATE_BNDCFG_SIZE	1088
> -#define X86_XSTATE_AVX512_SIZE	2688
> -#define X86_XSTATE_PKRU_SIZE	2696
> -#define X86_XSTATE_MAX_SIZE	2696
>  
>  
>  /* In case one of the MPX XCR0 bits is set we consider we have MPX.  */
> @@ -112,13 +107,6 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
>  #define HAS_AVX512(XCR0) (((XCR0) & X86_XSTATE_AVX512) != 0)
>  #define HAS_PKRU(XCR0) (((XCR0) & X86_XSTATE_PKRU) != 0)
>  
> -/* Get I386 XSAVE extended state size.  */
> -#define X86_XSTATE_SIZE(XCR0) \
> -    (HAS_PKRU (XCR0) ? X86_XSTATE_PKRU_SIZE : \
> -     (HAS_AVX512 (XCR0) ? X86_XSTATE_AVX512_SIZE : \
> -      (HAS_MPX (XCR0) ? X86_XSTATE_BNDCFG_SIZE : \
> -       (HAS_AVX (XCR0) ? X86_XSTATE_AVX_SIZE : X86_XSTATE_SSE_SIZE))))
> -
>  /* Initial value for fctrl register, as defined in the X86 manual, and
>     confirmed in the (Linux) kernel source.  When the x87 floating point
>     feature is not enabled in an inferior we use this as the value of the
> -- 
> 2.40.0
> 

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v6 15/15] gdbserver: Simplify handling of ZMM registers.
  2023-07-14 15:51 ` [PATCH v6 15/15] gdbserver: Simplify handling of ZMM registers John Baldwin
@ 2023-08-28 20:57   ` Simon Marchi
  0 siblings, 0 replies; 58+ messages in thread
From: Simon Marchi @ 2023-08-28 20:57 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 7/14/23 11:51, John Baldwin wrote:
> - Reuse num_xmm_registers directly for the count of ZMM0-15 registers
>   as is already done for the YMM registers for AVX rather than using
>   a new variable that is always the same.
> 
> - Replace 3 identical variables for the count of upper ZMM16-31
>   registers with a single variable.  Make use of this to merge
>   various loops working on the ZMM XSAVE region so that all of the
>   handling for the various sub-registers in this region are always
>   handled in a single loop.
> 
> - While here, fix some bugs in i387_cache_to_xsave on where if
>   X86_XSTATE_ZMM was set on i386 (e.g. a 32-bit process on a 64-bit
>   kernel), the -1 register nums would wrap around and store the
>   value of GPRs in the XSAVE area.  This should be harmless, but
>   is definitely odd.  Instead, check num_zmm_high_registers directly
>   when checking X86_XSTATE_ZMM and skip the ZMM region handling
>   entirely if the register count is 0.
> ---
>  gdbserver/i387-fp.cc | 132 +++++++++++++++----------------------------
>  1 file changed, 46 insertions(+), 86 deletions(-)
> 
> diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
> index f53a6cfc477..91d3a0b8ca3 100644
> --- a/gdbserver/i387-fp.cc
> +++ b/gdbserver/i387-fp.cc
> @@ -267,12 +267,8 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
>  
>    /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
>    int num_xmm_registers = amd64 ? 16 : 8;
> -  /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm.  */
> -  int num_avx512_zmmh_low_registers = num_xmm_registers;
> -  /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
> -  int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
> -  int num_avx512_ymmh_registers = amd64 ? 16 : 0;
> -  int num_avx512_xmm_registers = amd64 ? 16 : 0;
> +  /* AVX512 adds 16 extra ZMM regs in Amd64 mode, but none in I386 mode.*/
> +  int num_zmm_high_registers = amd64 ? 16 : 0;

The naming of these variables is confusing because "high" can mean the
high parts of the registers, or it can mean registers 16 to 31.  I wish
we could find different words to express both things.  But at least your
patch doesn't make things worse (it makes things better by eliminating
some variables).

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 58+ messages in thread

end of thread, other threads:[~2023-08-28 20:57 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-14 15:51 [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
2023-07-14 15:51 ` [PATCH v6 01/15] x86: Add an x86_xsave_layout structure to handle " John Baldwin
2023-07-26 19:22   ` Simon Marchi
2023-07-26 21:27     ` John Baldwin
2023-07-26 22:51       ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 02/15] gdb: Store an x86_xsave_layout in i386_gdbarch_tdep John Baldwin
2023-07-14 15:51 ` [PATCH v6 03/15] core: Support fetching x86 XSAVE layout from architectures John Baldwin
2023-07-26 19:37   ` Simon Marchi
2023-07-26 21:28     ` John Baldwin
2023-07-14 15:51 ` [PATCH v6 04/15] nat/x86-cpuid.h: Add x86_cpuid_count wrapper around __get_cpuid_count John Baldwin
2023-07-26 19:41   ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 05/15] x86 nat: Add helper functions to save the XSAVE layout for the host John Baldwin
2023-07-26 19:48   ` Simon Marchi
2023-07-26 21:37     ` John Baldwin
2023-07-14 15:51 ` [PATCH v6 06/15] gdb: Update x86 FreeBSD architectures to support XSAVE layouts John Baldwin
2023-07-26 20:04   ` Simon Marchi
2023-07-26 21:43     ` John Baldwin
2023-07-28 21:23   ` [PATCH v6a " John Baldwin
2023-08-28 16:01     ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 07/15] gdb: Support XSAVE layouts for the current host in the FreeBSD x86 targets John Baldwin
2023-07-26 20:26   ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 08/15] gdb: Update x86 Linux architectures to support XSAVE layouts John Baldwin
2023-07-26 20:45   ` Simon Marchi
2023-07-26 21:16     ` John Baldwin
2023-07-27 21:48       ` Simon Marchi
2023-07-28 16:30         ` John Baldwin
2023-07-28 17:58           ` Simon Marchi
2023-07-28 21:30             ` John Baldwin
2023-07-28 21:29   ` [PATCH v6a " John Baldwin
2023-08-14 17:52     ` John Baldwin
2023-08-28 16:21     ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 09/15] gdb: Support XSAVE layouts for the current host in the Linux x86 targets John Baldwin
2023-07-26 20:51   ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 10/15] gdb: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
2023-08-28 16:34   ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 11/15] gdbserver: Add a function to set the XSAVE mask and size John Baldwin
2023-08-28 16:46   ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 12/15] gdbserver: Refactor the legacy region within the xsave struct John Baldwin
2023-08-28 16:50   ` Simon Marchi
2023-08-28 17:32     ` John Baldwin
2023-07-14 15:51 ` [PATCH v6 13/15] gdbserver: Use x86_xstate_layout to parse the XSAVE extended state area John Baldwin
2023-08-28 18:15   ` Simon Marchi
2023-08-28 18:37     ` John Baldwin
2023-07-14 15:51 ` [PATCH v6 14/15] x86: Remove X86_XSTATE_SIZE and related constants John Baldwin
2023-08-28 20:38   ` Simon Marchi
2023-07-14 15:51 ` [PATCH v6 15/15] gdbserver: Simplify handling of ZMM registers John Baldwin
2023-08-28 20:57   ` Simon Marchi
2023-07-14 15:58 ` [PATCH v6 00/15] Handle variable XSAVE layouts John Baldwin
2023-07-26  8:31   ` Willgerodt, Felix
2023-07-25 17:17 ` Keith Seitz
2023-07-25 18:15   ` John Baldwin
2023-07-25 18:43     ` Keith Seitz
2023-07-25 18:59       ` John Baldwin
2023-07-25 20:42         ` Keith Seitz
2023-07-25 22:05           ` John Baldwin
2023-07-26 22:31             ` John Baldwin
2023-07-27 21:36               ` Keith Seitz
2023-07-28 16:35                 ` John Baldwin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).