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
next prev parent 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