Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Vignesh Balasubramanian <vigbalas@amd.com>
To: <gdb-patches@sourceware.org>, <jinisusan.george@amd.com>,
	<christina.schimpe@intel.com>, <AlokKumar.Sharma@amd.com>,
	<jhb@FreeBSD.org>,  <simark@simark.ca>
Cc: Vignesh Balasubramanian <vigbalas@amd.com>
Subject: [PATCH 32 1/2] core: Consume the new .note section that contains descriptions of xsave layout
Date: Mon, 8 Dec 2025 14:08:19 +0530	[thread overview]
Message-ID: <20251208083819.2560894-2-vigbalas@amd.com> (raw)
In-Reply-To: <20251208083819.2560894-1-vigbalas@amd.com>

Currently, we use some heuristics [1] to find the offsets of the xsave features
present in the xsave layouts of core files using XCR0 value.
While GDB can currently access the values of AVX-512 and PKRU registers on
AMD and Intel CPUs using existing heuristics, this approach may fail if the
XSAVE register offsets vary — even with the same XCR0 value.

Additionally, the current implementation may not scale effectively if a new
XSAVE state is introduced that matches the size of the existing states.

Linux kernel from 6.12 [2] creates a new .note section "NT_X86_XSAVE_LAYOUT"
which contains information on the size, offset and flags of each
xsave feature present when core is dumped.

[1] https://github.com/bminor/binutils-gdb/commit/c689d1fe58b2c0faf51e4f574d50271f1d0648e3
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/arch/x86/kernel/fpu/xstate.c?id=ba386777a30b38dabcc7fb8a89ec2869a09915f7

Co-Authored-By: Jini Susan George <jinisusan.george@amd.com>

V2 -> V3:
Removed "struct x86_xfeat_component" and used "extract_unsigned_integer".
"if conditions" of i386_linux_core_read_xsave_info is modified.
Renamed macro "X86_XSTATE_TILE_DATA " and X86_XSTATE_PASID".
Some NITs

---
 gdb/amd64-linux-tdep.c  |  2 +-
 gdb/i386-linux-tdep.c   | 25 +++++++++---
 gdb/i386-linux-tdep.h   |  3 +-
 gdb/i387-tdep.c         | 86 +++++++++++++++++++++++++++++++++++++++++
 gdb/i387-tdep.h         | 12 ++++++
 gdbsupport/x86-xstate.h |  4 ++
 6 files changed, 124 insertions(+), 8 deletions(-)

diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index 284c956cd9b..393c0fd2adc 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1614,7 +1614,7 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
 {
   /* Linux/x86-64.  */
   x86_xsave_layout layout;
-  uint64_t xstate_bv = i386_linux_core_read_xsave_info (abfd, layout);
+  uint64_t xstate_bv = i386_linux_core_read_xsave_info (gdbarch, abfd, layout);
   if (xstate_bv == 0)
     xstate_bv = X86_XSTATE_SSE_MASK;
 
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 1d6abe2f546..8a7f416fb66 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -1077,7 +1077,8 @@ static int i386_linux_sc_reg_offset[] =
 /* See i386-linux-tdep.h.  */
 
 uint64_t
-i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
+i386_linux_core_read_xsave_info (struct gdbarch *gdbarch, bfd *abfd,
+				 x86_xsave_layout &layout)
 {
   asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
   if (xstate == nullptr)
@@ -1099,10 +1100,22 @@ i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
 
   uint64_t xcr0 = bfd_get_64 (abfd, contents);
 
-  if (!i387_guess_xsave_layout (xcr0, size, layout))
-    return 0;
+  /* Try using the note describing the XSAVE layout, if present.  */
+  if (asection *xsave_layout_desc
+	= bfd_get_section_by_name (abfd, ".reg-xsave-layout");
+      xsave_layout_desc != nullptr)
+    {
+      if (i387_read_xsave_layout_desc (gdbarch, abfd, size,
+						layout, xsave_layout_desc))
+	return xcr0;
+    }
 
-  return xcr0;
+  /* Otherwise, fallback to guessing the layout based on the size of the XSAVE
+     buffer.  */
+  if (i387_guess_xsave_layout (xcr0, size, layout))
+    return xcr0;
+
+  return 0;
 }
 
 /* See i386-linux-tdep.h.  */
@@ -1111,7 +1124,7 @@ bool
 i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch, bfd &cbfd,
 				       x86_xsave_layout &layout)
 {
-  return i386_linux_core_read_xsave_info (&cbfd, layout) != 0;
+  return i386_linux_core_read_xsave_info (gdbarch, &cbfd, layout) != 0;
 }
 
 /* See arch/x86-linux-tdesc.h.  */
@@ -1131,7 +1144,7 @@ i386_linux_core_read_description (struct gdbarch *gdbarch,
 {
   /* Linux/i386.  */
   x86_xsave_layout layout;
-  uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
+  uint64_t xcr0 = i386_linux_core_read_xsave_info (gdbarch, abfd, layout);
 
   if (xcr0 == 0)
     {
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
index e75e53aba95..73c3729e885 100644
--- a/gdb/i386-linux-tdep.h
+++ b/gdb/i386-linux-tdep.h
@@ -58,7 +58,8 @@ enum i386_linux_regnum
 
    Otherwise, return 0 to indicate no state was found and leave LAYOUT
    untouched.  */
-extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
+extern uint64_t i386_linux_core_read_xsave_info (struct gdbarch *gdbarch,
+						 bfd *abfd,
 						 x86_xsave_layout &layout);
 
 /* Implement the core_read_x86_xsave_layout gdbarch method.  */
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index ff66712ed0d..f6bee42fc7d 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -959,6 +959,92 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
 
 /* See i387-tdep.h.  */
 
+bool
+i387_read_xsave_layout_desc (struct gdbarch *gdbarch, bfd *abfd,
+			     size_t xsave_size,
+			     x86_xsave_layout &layout,
+			     asection* xsave_layout_desc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte *buf = (gdb_byte *) xmalloc(bfd_section_size(xsave_layout_desc));
+
+  if (!bfd_get_section_contents (abfd, xsave_layout_desc, buf, 0,
+				 xsave_layout_desc->size))
+    {
+      warning (_("Couldn't read XSAVE Layout description records from"
+		 "'.reg-xsave-layout' section in core file."));
+      return false;
+    }
+
+  /* This note section in linux is an array of below struct:
+     struct x86_xfeat_component
+     {
+       uint32_t type;
+       uint32_t size;
+       uint32_t offset;
+       uint32_t flags;
+     };
+     16 bytes for each record.
+     We are interested in type (0th byte) and offset (8th byte).  */
+
+  #define SIZEOF_XFEAT_TYPE 4
+  #define SIZEOF_XFEAT_OFFSET 4
+  #define OFFSET_AT_RECORD 8
+  #define SIZE_OF_RECORD 16
+
+  for (int i = 0; i < xsave_layout_desc->size; )
+    {
+      switch (extract_unsigned_integer(buf + i, SIZEOF_XFEAT_TYPE, byte_order))
+	{
+	  case X86_XSTATE_AVX_ID:
+	    layout.avx_offset = extract_unsigned_integer(buf + (i + OFFSET_AT_RECORD),
+							 SIZEOF_XFEAT_OFFSET,
+							 byte_order);
+	    break;
+	  case X86_XSTATE_BNDREGS_ID:
+	  case X86_XSTATE_BNDCFG_ID:
+	    /* MPX support in GDB is deprecated from GDB 15.2 Release. */
+	    continue;
+	  case X86_XSTATE_K_ID:
+	    layout.k_offset = extract_unsigned_integer(buf + (i + OFFSET_AT_RECORD),
+						       SIZEOF_XFEAT_OFFSET,
+						       byte_order);
+	    break;
+	  case X86_XSTATE_ZMM_H_ID:
+	    layout.zmm_h_offset = extract_unsigned_integer(buf + (i + OFFSET_AT_RECORD),
+							   SIZEOF_XFEAT_OFFSET,
+							   byte_order);
+	    break;
+	  case X86_XSTATE_ZMM_ID:
+	    layout.zmm_offset = extract_unsigned_integer(buf + (i + OFFSET_AT_RECORD),
+							 SIZEOF_XFEAT_OFFSET,
+							 byte_order);
+	    break;
+	  case X86_XSTATE_PKRU_ID:
+	    layout.pkru_offset = extract_unsigned_integer(buf + (i + OFFSET_AT_RECORD),
+							  SIZEOF_XFEAT_OFFSET,
+							  byte_order);
+	    break;
+	  case X86_XSTATE_PASID_ID ... X86_XSTATE_TILEDATA_ID:
+	    /* These IDs are not part of x86_xsave_layout currently,
+	       so we ignore. */
+	    continue;
+	  default:
+	    /* 19 - 31 are reserved, shouldn't be any record with these IDs. */
+	    warning (_("Unhandled xsave feature record type."));
+	    break;
+	}
+
+      i += SIZE_OF_RECORD;
+    }
+
+  xfree (buf);
+  layout.sizeof_xsave = xsave_size;
+  return true;
+}
+
+/* See i387-tdep.h.  */
+
 x86_xsave_layout
 i387_fallback_xsave_layout (uint64_t xcr0)
 {
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index ed4df1d2458..becbed92260 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -139,6 +139,18 @@ 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);
 
+/* Read offsets of xsave features in XSAVE Layout from the .note
+   section generated by Linux.
+   This .note section contains offset and size information of xsave
+   feature present in the machine where core file is dumped and it helps
+   to avoid guessing or hardcoding the offsets.
+   This feature is available from Linux 6.12.  */
+
+extern bool i387_read_xsave_layout_desc (struct gdbarch *gdbarch, bfd *abfd,
+					 size_t xsave_size,
+					 x86_xsave_layout &layout,
+					 asection *xsave_layout_desc);
+
 /* Compute an XSAVE layout based on the XCR0 bitmask.  This is used
    as a fallback if a target does not provide an XSAVE layout.  */
 
diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
index 6657c450c88..a9ab39152ad 100644
--- a/gdbsupport/x86-xstate.h
+++ b/gdbsupport/x86-xstate.h
@@ -24,11 +24,15 @@
 #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
+#define X86_XSTATE_PASID_ID	10
 #define X86_XSTATE_CET_U_ID	11
+#define X86_XSTATE_TILEDATA_ID	18
 
 /* The extended state feature bits.  */
 #define X86_XSTATE_X87		(1ULL << X86_XSTATE_X87_ID)
-- 
2.34.1


  reply	other threads:[~2025-12-08  8:41 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-08  8:38 [PATCH 32 0/2] Handle the new .note section introduced in Linux Vignesh Balasubramanian
2025-12-08  8:38 ` Vignesh Balasubramanian [this message]
2025-12-08  8:38 ` [PATCH 32 2/2] gcore: Create a new .note section for x86 Vignesh Balasubramanian
2025-12-14 13:39 ` [PATCH 32 0/2] Handle the new .note section introduced in Linux Schimpe, Christina
2026-01-06  6:48   ` Balasubrmanian, Vignesh
2026-03-06  7:08     ` Schimpe, Christina
2026-03-06  7:42       ` Balasubrmanian, Vignesh
2026-03-06  8:13         ` Schimpe, Christina
2026-03-11  9:50           ` Schimpe, Christina
2026-03-13 14:08             ` Schimpe, Christina
2026-03-17 10:02               ` Schimpe, Christina
2026-02-08  4:18   ` Vignesh Balasubramanian
2026-03-16 12:59 ` [PATCH 32 0/2] Handle the new .note section introduced in Linux Schimpe, Christina

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251208083819.2560894-2-vigbalas@amd.com \
    --to=vigbalas@amd.com \
    --cc=AlokKumar.Sharma@amd.com \
    --cc=christina.schimpe@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=jhb@FreeBSD.org \
    --cc=jinisusan.george@amd.com \
    --cc=simark@simark.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox