Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc
       [not found] <20260930151403.774660-1-ssbssa.ref@yahoo.de>
@ 2026-09-30 15:11 ` Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 2/9] Windows gdb: Use allocated buffer for CONTEXT Hannes Domani
                     ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

_aligned_malloc has swapped arguments, and you have to use _aligned_free
to free the memory afterwards.

This is enough to make i386-sse.exp pass, and i386-avx.exp will pass at
the end of this series.

Approved-By: Tom Tromey <tom@tromey.com>
---
v2:
  - Mention which test pass after the change in the commit message
v3: no changes
v4: no changes
---
 gdb/testsuite/gdb.arch/i386-avx.c         |  2 +-
 gdb/testsuite/gdb.arch/i386-sse.c         |  2 +-
 gdb/testsuite/lib/precise-aligned-alloc.c | 20 ++++++++++++++++++++
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/gdb/testsuite/gdb.arch/i386-avx.c b/gdb/testsuite/gdb.arch/i386-avx.c
index 85bb974f4c4..c218b0a194c 100644
--- a/gdb/testsuite/gdb.arch/i386-avx.c
+++ b/gdb/testsuite/gdb.arch/i386-avx.c
@@ -125,7 +125,7 @@ main (int argc, char **argv)
 
   puts ("Bye!"); /* second breakpoint here */
 
-  free (allocated_ptr);
+  aligned_free (allocated_ptr);
 
   return 0;
 }
diff --git a/gdb/testsuite/gdb.arch/i386-sse.c b/gdb/testsuite/gdb.arch/i386-sse.c
index 21264ed74e7..5210aee12c3 100644
--- a/gdb/testsuite/gdb.arch/i386-sse.c
+++ b/gdb/testsuite/gdb.arch/i386-sse.c
@@ -134,7 +134,7 @@ main (int argc, char **argv)
       puts ("Bye!"); /* second breakpoint here */
     }
 
-  free (allocated_ptr);
+  aligned_free (allocated_ptr);
 
   return 0;
 }
diff --git a/gdb/testsuite/lib/precise-aligned-alloc.c b/gdb/testsuite/lib/precise-aligned-alloc.c
index 888814f12ef..1db35528bc8 100644
--- a/gdb/testsuite/lib/precise-aligned-alloc.c
+++ b/gdb/testsuite/lib/precise-aligned-alloc.c
@@ -21,6 +21,26 @@
 #include <string.h>
 #include <stdint.h>
 
+#ifdef _WIN32
+static void *
+aligned_alloc (size_t alignment, size_t size)
+{
+  return _aligned_malloc (size, alignment);
+}
+
+static void
+aligned_free (void *ptr)
+{
+  _aligned_free (ptr);
+}
+#else
+static void
+aligned_free (void *ptr)
+{
+  free (ptr);
+}
+#endif
+
 /* Return true if address P is ALIGNMENT-byte aligned.  */
 
 static int
-- 
2.55.0


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

* [PATCH v4 2/9] Windows gdb: Use allocated buffer for CONTEXT
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 3/9] Windows gdb: Remove mappings member from windows_per_inferior Hannes Domani
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This is done in preparation for the XState functions, because the
extended registers are stored directly after the CONTEXT, and its actual
size depends on the available XState features.

Approved-By: Tom Tromey <tom@tromey.com>
---
v3:
  - fixed missing newline
  - merged initialize_context into the windows_process_info constructor
v4: no changes
---
 gdb/aarch64-windows-nat.c      | 16 ++++++++--------
 gdb/nat/windows-nat.c          | 22 ++++++++++++++++++++++
 gdb/nat/windows-nat.h          | 20 +++++++++-----------
 gdbserver/win32-aarch64-low.cc | 10 +++++-----
 4 files changed, 44 insertions(+), 24 deletions(-)

diff --git a/gdb/aarch64-windows-nat.c b/gdb/aarch64-windows-nat.c
index ff2c9762467..630704a8caf 100644
--- a/gdb/aarch64-windows-nat.c
+++ b/gdb/aarch64-windows-nat.c
@@ -185,7 +185,7 @@ aarch64_windows_nat_target::cleanup_windows_arch ()
 void
 aarch64_windows_per_inferior::fill_thread_context (windows_thread_info *th)
 {
-  CONTEXT *context = &th->context;
+  CONTEXT *context = th->context;
 
   if (context->ContextFlags == 0)
     {
@@ -199,7 +199,7 @@ aarch64_windows_per_inferior::fill_thread_context (windows_thread_info *th)
 void
 aarch64_windows_per_inferior::invalidate_thread_context (windows_thread_info *th)
 {
-  CONTEXT *context = &th->context;
+  CONTEXT *context = th->context;
   context->ContextFlags = 0;
 }
 
@@ -209,7 +209,7 @@ void
 aarch64_windows_nat_target::thread_context_continue (windows_thread_info *th,
 						     int killed)
 {
-  CONTEXT *context = &th->context;
+  CONTEXT *context = th->context;
 
   if (th->debug_registers_changed)
     {
@@ -250,9 +250,9 @@ aarch64_windows_nat_target::thread_context_step (windows_thread_info *th,
 						 bool enable)
 {
   if (enable)
-    th->context.Cpsr |= 0x200000;
+    th->context->Cpsr |= 0x200000;
   else
-    th->context.Cpsr &= ~0x200000;
+    th->context->Cpsr &= ~0x200000;
 }
 
 /* See windows-nat.h.  */
@@ -263,7 +263,7 @@ aarch64_windows_nat_target::fetch_one_register (struct regcache *regcache,
 {
   gdb_assert (r >= 0);
 
-  char *context_ptr = (char *) &th->context;
+  char *context_ptr = (char *) th->context;
   char *context_offset = context_ptr + aarch64_windows_process.mappings[r];
   struct gdbarch *gdbarch = regcache->arch ();
 
@@ -292,9 +292,9 @@ aarch64_windows_nat_target::store_one_register (const struct regcache *regcache,
 						windows_thread_info *th, int r)
 {
   gdb_assert (r >= 0);
-  gdb_assert (th->context.ContextFlags != 0);
+  gdb_assert (th->context->ContextFlags != 0);
 
-  char *context_ptr = (char *) &th->context;
+  char *context_ptr = (char *) th->context;
 
   regcache->raw_collect (r, context_ptr + aarch64_windows_process.mappings[r]);
 }
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index e975892f487..974b1d3535b 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -79,6 +79,28 @@ DeleteProcThreadAttributeList_ftype *DeleteProcThreadAttributeList;
   debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
 			      ## __VA_ARGS__)
 
+windows_thread_info::windows_thread_info (windows_process_info *proc_,
+					  DWORD tid_, HANDLE h_, CORE_ADDR tlb)
+  : proc (proc_),
+    tid (tid_),
+    h (h_),
+    thread_local_base (tlb)
+{
+#ifdef __x86_64__
+  if (proc->wow64_process)
+    {
+      context_buffer.reset (xmalloc (sizeof (WOW64_CONTEXT)));
+      wow64_context = (WOW64_CONTEXT *) context_buffer.get ();
+    }
+  else
+#endif
+    {
+      context_buffer.reset (xmalloc (sizeof (CONTEXT)));
+      context = (CONTEXT *) context_buffer.get ();
+    }
+  *proc->context_flags_ptr (this) = 0;
+}
+
 void
 windows_thread_info::suspend ()
 {
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index fcdf43e270e..c153ad2c82c 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -63,13 +63,7 @@ enum stopping_kind
 struct windows_thread_info
 {
   windows_thread_info (windows_process_info *proc_,
-		       DWORD tid_, HANDLE h_, CORE_ADDR tlb)
-    : proc (proc_),
-      tid (tid_),
-      h (h_),
-      thread_local_base (tlb)
-  {
-  }
+		       DWORD tid_, HANDLE h_, CORE_ADDR tlb);
 
   DISABLE_COPY_AND_ASSIGN (windows_thread_info);
 
@@ -182,9 +176,9 @@ struct windows_thread_info
   /* The context of the thread, including any manipulations.  */
   union
   {
-    CONTEXT context {};
+    CONTEXT *context = nullptr;
 #ifdef __x86_64__
-    WOW64_CONTEXT wow64_context;
+    WOW64_CONTEXT *wow64_context;
 #endif
   };
 
@@ -203,6 +197,10 @@ struct windows_thread_info
 
   /* The name of the thread.  */
   gdb::unique_xmalloc_ptr<char> name;
+
+  /* The buffer for the thread context, including any XState registers if
+     available.  */
+  gdb::unique_xmalloc_ptr<void> context_buffer;
 };
 
 enum handle_exception_result
@@ -317,10 +315,10 @@ struct windows_process_info
   {
 #ifdef __x86_64__
     if (wow64_process)
-      return function (th != nullptr ? &th->wow64_context : nullptr);
+      return function (th != nullptr ? th->wow64_context : nullptr);
     else
 #endif
-      return function (th != nullptr ? &th->context : nullptr);
+      return function (th != nullptr ? th->context : nullptr);
   }
 
   DWORD *context_flags_ptr (windows_thread_info *th)
diff --git a/gdbserver/win32-aarch64-low.cc b/gdbserver/win32-aarch64-low.cc
index 5a7b72155db..e94548b6fef 100644
--- a/gdbserver/win32-aarch64-low.cc
+++ b/gdbserver/win32-aarch64-low.cc
@@ -169,7 +169,7 @@ aarch64_initial_stuff (process_info *proc)
 static void
 aarch64_get_thread_context (windows_thread_info *th)
 {
-  CONTEXT *context = &th->context;
+  CONTEXT *context = th->context;
 
   context->ContextFlags = (WindowsContext<decltype(context)>::full
 			   | WindowsContext<decltype(context)>::floating
@@ -193,7 +193,7 @@ aarch64_prepare_to_resume (windows_thread_info *th)
     {
       win32_require_context (th);
 
-      CONTEXT *context = &th->context;
+      CONTEXT *context = th->context;
 
       for (int i = 0; i < aarch64_num_bp_regs; i++)
 	{
@@ -223,7 +223,7 @@ aarch64_thread_added (windows_thread_info *th)
 static void
 aarch64_single_step (windows_thread_info *th)
 {
-  th->context.Cpsr |= 0x200000;
+  th->context->Cpsr |= 0x200000;
 }
 
 /* An array of offset mappings into a Win32 Context structure.
@@ -322,7 +322,7 @@ aarch64_fetch_inferior_register (struct regcache *regcache,
   int mappings_count;
   get_mappings (mappings, mappings_count);
 
-  char *context_ptr = (char *) &th->context;
+  char *context_ptr = (char *) th->context;
   char *context_offset;
   if (r < mappings_count)
     context_offset = context_ptr + mappings[r];
@@ -341,7 +341,7 @@ aarch64_store_inferior_register (struct regcache *regcache,
   int mappings_count;
   get_mappings (mappings, mappings_count);
 
-  char *context_ptr = (char *) &th->context;
+  char *context_ptr = (char *) th->context;
   char *context_offset;
   if (r < mappings_count)
     context_offset = context_ptr + mappings[r];
-- 
2.55.0


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

* [PATCH v4 3/9] Windows gdb: Remove mappings member from windows_per_inferior
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 2/9] Windows gdb: Use allocated buffer for CONTEXT Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 4/9] Windows gdb: Refactor getting pointer to register inside context Hannes Domani
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

It's not really that useful, and simplifies later XState changes.

Approved-By: Tom Tromey <tom@tromey.com>
---
v3: no changes
v4: no changes
---
 gdb/aarch64-windows-nat.c |  6 ++----
 gdb/windows-nat.h         | 18 ------------------
 gdb/x86-windows-nat.c     | 34 ++++++++++++++++++++++------------
 3 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/gdb/aarch64-windows-nat.c b/gdb/aarch64-windows-nat.c
index 630704a8caf..be900439047 100644
--- a/gdb/aarch64-windows-nat.c
+++ b/gdb/aarch64-windows-nat.c
@@ -168,8 +168,6 @@ aarch64_windows_nat_target::initialize_windows_arch (bool attaching)
 {
   memset (&aarch64_windows_process.dr_state, 0,
 	  sizeof (aarch64_windows_process.dr_state));
-
-  aarch64_windows_process.mappings = aarch64_mappings;
 }
 
 /* See windows-nat.h.  */
@@ -264,7 +262,7 @@ aarch64_windows_nat_target::fetch_one_register (struct regcache *regcache,
   gdb_assert (r >= 0);
 
   char *context_ptr = (char *) th->context;
-  char *context_offset = context_ptr + aarch64_windows_process.mappings[r];
+  char *context_offset = context_ptr + aarch64_mappings[r];
   struct gdbarch *gdbarch = regcache->arch ();
 
   gdb_assert (!gdbarch_read_pc_p (gdbarch));
@@ -296,7 +294,7 @@ aarch64_windows_nat_target::store_one_register (const struct regcache *regcache,
 
   char *context_ptr = (char *) th->context;
 
-  regcache->raw_collect (r, context_ptr + aarch64_windows_process.mappings[r]);
+  regcache->raw_collect (r, context_ptr + aarch64_mappings[r]);
 }
 
 /* See windows-nat.h.  */
diff --git a/gdb/windows-nat.h b/gdb/windows-nat.h
index 77834db1388..e0e147856fb 100644
--- a/gdb/windows-nat.h
+++ b/gdb/windows-nat.h
@@ -142,24 +142,6 @@ struct windows_per_inferior : public windows_nat::windows_process_info
   void *wow64_dbgbreak = nullptr;
 #endif
 
-  /* This vector maps GDB's idea of a register's number into an offset
-     in the windows exception context vector.
-
-     It also contains the bit mask needed to load the register in question.
-
-     The contents of this table can only be computed by the units
-     that provide CPU-specific support for Windows native debugging.
-
-     One day we could read a reg, we could inspect the context we
-     already have loaded, if it doesn't have the bit set that we need,
-     we read that set of registers in using GetThreadContext.  If the
-     context already contains what we need, we just unpack it.  Then to
-     write a register, first we have to ensure that the context contains
-     the other regs of the group, and then we copy the info in and set
-     out bit.  */
-
-  const int *mappings = nullptr;
-
   std::vector<windows_solib> solibs;
 
 #ifdef __CYGWIN__
diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
index 2f556e47b39..b3ad8594020 100644
--- a/gdb/x86-windows-nat.c
+++ b/gdb/x86-windows-nat.c
@@ -85,16 +85,10 @@ x86_windows_nat_target::initialize_windows_arch (bool attaching)
     = !attaching && x86_windows_process.wow64_process;
 
   if (!x86_windows_process.wow64_process)
-    {
-      x86_windows_process.mappings = amd64_mappings;
-      x86_windows_process.segment_register_p = amd64_windows_segment_register_p;
-    }
+    x86_windows_process.segment_register_p = amd64_windows_segment_register_p;
   else
 #endif
-    {
-      x86_windows_process.mappings = i386_mappings;
-      x86_windows_process.segment_register_p = i386_windows_segment_register_p;
-    }
+    x86_windows_process.segment_register_p = i386_windows_segment_register_p;
 }
 
 /* See windows-nat.h.  */
@@ -242,7 +236,15 @@ x86_windows_nat_target::fetch_one_register (struct regcache *regcache,
       return (char *) context;
     });
 
-  char *context_offset = context_ptr + x86_windows_process.mappings[r];
+  const int *mappings;
+#ifdef __x86_64__
+  if (!x86_windows_process.wow64_process)
+    mappings = amd64_mappings;
+  else
+#endif
+    mappings = i386_mappings;
+
+  char *context_offset = context_ptr + mappings[r];
   struct gdbarch *gdbarch = regcache->arch ();
   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
@@ -308,6 +310,14 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache,
       return (char *) context;
     });
 
+  const int *mappings;
+#ifdef __x86_64__
+  if (!x86_windows_process.wow64_process)
+    mappings = amd64_mappings;
+  else
+#endif
+    mappings = i386_mappings;
+
   struct gdbarch *gdbarch = regcache->arch ();
   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
@@ -319,7 +329,7 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache,
     {
       gdb_byte bytes[4];
       regcache->raw_collect (r, bytes);
-      memcpy (context_ptr + x86_windows_process.mappings[r], bytes, 2);
+      memcpy (context_ptr + mappings[r], bytes, 2);
     }
   else if (r == I387_FOP_REGNUM (tdep))
     {
@@ -328,10 +338,10 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache,
       /* The value of FOP occupies the top two bytes in the context,
 	 so write the two low-order bytes from the cache into the
 	 appropriate spot.  */
-      memcpy (context_ptr + x86_windows_process.mappings[r] + 2, bytes, 2);
+      memcpy (context_ptr + mappings[r] + 2, bytes, 2);
     }
   else
-    regcache->raw_collect (r, context_ptr + x86_windows_process.mappings[r]);
+    regcache->raw_collect (r, context_ptr + mappings[r]);
 }
 
 /* See windows-nat.h.  */
-- 
2.55.0


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

* [PATCH v4 4/9] Windows gdb: Refactor getting pointer to register inside context
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 2/9] Windows gdb: Use allocated buffer for CONTEXT Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 3/9] Windows gdb: Remove mappings member from windows_per_inferior Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 5/9] Windows gdb: Prepare XState functions Hannes Domani
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

These get_context_reg_ptr helper functions will be extended for XState
registers later.

Approved-By: Tom Tromey <tom@tromey.com>
---
v3: no changes
v4: no changes
---
 gdb/amd64-windows-nat.c     |  3 ++
 gdb/i386-windows-nat.c      |  3 ++
 gdb/windows-nat.h           |  6 +++
 gdb/x86-windows-nat.c       | 75 ++++++++++++++++++++++---------------
 gdbserver/win32-i386-low.cc | 46 +++++++++++++++--------
 5 files changed, 87 insertions(+), 46 deletions(-)

diff --git a/gdb/amd64-windows-nat.c b/gdb/amd64-windows-nat.c
index cca606b5200..9d83a5f8334 100644
--- a/gdb/amd64-windows-nat.c
+++ b/gdb/amd64-windows-nat.c
@@ -86,6 +86,9 @@ const int amd64_mappings[] =
 };
 #undef context_offset
 
+const int amd64_mappings_count
+  = sizeof (amd64_mappings) / sizeof (amd64_mappings[0]);
+
 /* segment_register_p_ftype implementation for amd64.  */
 
 int
diff --git a/gdb/i386-windows-nat.c b/gdb/i386-windows-nat.c
index 991f301cad1..151b778036c 100644
--- a/gdb/i386-windows-nat.c
+++ b/gdb/i386-windows-nat.c
@@ -74,6 +74,9 @@ const int i386_mappings[] =
 #undef context_offset
 #undef CONTEXT
 
+const int i386_mappings_count
+  = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
+
 /* segment_register_p_ftype implementation for x86.  */
 
 int
diff --git a/gdb/windows-nat.h b/gdb/windows-nat.h
index e0e147856fb..2fb2e3abf2e 100644
--- a/gdb/windows-nat.h
+++ b/gdb/windows-nat.h
@@ -393,12 +393,18 @@ int i386_windows_segment_register_p (int regnum);
 /* context register offsets for x86.  */
 extern const int i386_mappings[];
 
+/* number of context register offsets for x86.  */
+extern const int i386_mappings_count;
+
 #ifdef __x86_64__
 /* segment_register_p_ftype implementation for amd64.  */
 int amd64_windows_segment_register_p (int regnum);
 
 /* context register offsets for amd64.  */
 extern const int amd64_mappings[];
+
+/* number of context register offsets for amd64.  */
+extern const int amd64_mappings_count;
 #endif
 
 /* Creates an iterator that works like all_matching_threads_iterator,
diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
index b3ad8594020..3af5ef4dae0 100644
--- a/gdb/x86-windows-nat.c
+++ b/gdb/x86-windows-nat.c
@@ -223,31 +223,53 @@ x86_windows_nat_target::thread_context_step (windows_thread_info *th,
     });
 }
 
-/* See windows-nat.h.  */
+/* Get pointer to register R inside CONTEXT.  */
 
-void
-x86_windows_nat_target::fetch_one_register (struct regcache *regcache,
-					    windows_thread_info *th, int r)
+template<typename Context>
+static char *
+get_context_reg_ptr (Context *context, int r)
 {
-  gdb_assert (r >= 0);
-
-  char *context_ptr = x86_windows_process.with_context (th, [] (auto *context)
-    {
-      return (char *) context;
-    });
-
   const int *mappings;
+  int mappings_count;
 #ifdef __x86_64__
   if (!x86_windows_process.wow64_process)
-    mappings = amd64_mappings;
+    {
+      mappings = amd64_mappings;
+      mappings_count = amd64_mappings_count;
+    }
   else
 #endif
-    mappings = i386_mappings;
+    {
+      mappings = i386_mappings;
+      mappings_count = i386_mappings_count;
+    }
+
+  char *context_offset;
+  if (r < mappings_count)
+    context_offset = (char *) context + mappings[r];
+  else
+    gdb_assert_not_reached ("invalid register number %d", r);
+
+  return context_offset;
+}
+
+/* See windows-nat.h.  */
+
+void
+x86_windows_nat_target::fetch_one_register (struct regcache *regcache,
+					    windows_thread_info *th, int r)
+{
+  gdb_assert (r >= 0);
 
-  char *context_offset = context_ptr + mappings[r];
   struct gdbarch *gdbarch = regcache->arch ();
   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
+  char *context_offset
+    = x86_windows_process.with_context (th, [&] (auto *context)
+    {
+      return get_context_reg_ptr (context, r);
+    });
+
   gdb_assert (!gdbarch_read_pc_p (gdbarch));
   gdb_assert (gdbarch_pc_regnum (gdbarch) >= 0);
   gdb_assert (!gdbarch_write_pc_p (gdbarch));
@@ -304,23 +326,16 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache,
 {
   gdb_assert (r >= 0);
 
-  char *context_ptr = x86_windows_process.with_context (th, [] (auto *context)
+  struct gdbarch *gdbarch = regcache->arch ();
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+
+  char *context_offset
+    = x86_windows_process.with_context (th, [&] (auto *context)
     {
       gdb_assert (context->ContextFlags != 0);
-      return (char *) context;
+      return get_context_reg_ptr (context, r);
     });
 
-  const int *mappings;
-#ifdef __x86_64__
-  if (!x86_windows_process.wow64_process)
-    mappings = amd64_mappings;
-  else
-#endif
-    mappings = i386_mappings;
-
-  struct gdbarch *gdbarch = regcache->arch ();
-  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
-
   /* GDB treats some registers as 32-bit, where they are in fact only
      16 bits long.  These cases must be handled specially to avoid
      overwriting other registers in the context.  */
@@ -329,7 +344,7 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache,
     {
       gdb_byte bytes[4];
       regcache->raw_collect (r, bytes);
-      memcpy (context_ptr + mappings[r], bytes, 2);
+      memcpy (context_offset, bytes, 2);
     }
   else if (r == I387_FOP_REGNUM (tdep))
     {
@@ -338,10 +353,10 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache,
       /* The value of FOP occupies the top two bytes in the context,
 	 so write the two low-order bytes from the cache into the
 	 appropriate spot.  */
-      memcpy (context_ptr + mappings[r] + 2, bytes, 2);
+      memcpy (context_offset + 2, bytes, 2);
     }
   else
-    regcache->raw_collect (r, context_ptr + mappings[r]);
+    regcache->raw_collect (r, context_offset);
 }
 
 /* See windows-nat.h.  */
diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
index 1aacd302074..b77f6adc6ed 100644
--- a/gdbserver/win32-i386-low.cc
+++ b/gdbserver/win32-i386-low.cc
@@ -473,22 +473,44 @@ is_segment_register (int r)
     return r >= I386_CS_REGNUM && r <= I386_GS_REGNUM;
 }
 
-/* Fetch register from gdbserver regcache data.  */
-static void
-i386_fetch_inferior_register (struct regcache *regcache,
-			      windows_thread_info *th, int r)
+/* Get pointer to register R inside CONTEXT.  */
+
+template<typename Context>
+static char *
+get_context_reg_ptr (Context *context, int r)
 {
   const int *mappings;
+  int mappings_count;
 #ifdef __x86_64__
   if (!windows_process.wow64_process)
-    mappings = amd64_mappings;
+    {
+      mappings = amd64_mappings;
+      mappings_count = sizeof (amd64_mappings) / sizeof (amd64_mappings[0]);
+    }
   else
 #endif
-    mappings = i386_mappings;
+    {
+      mappings = i386_mappings;
+      mappings_count = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
+    }
+
+  char *context_offset;
+  if (r < mappings_count)
+    context_offset = (char *) context + mappings[r];
+  else
+    gdb_assert_not_reached ("invalid register number %d", r);
+
+  return context_offset;
+}
 
+/* Fetch register from gdbserver regcache data.  */
+static void
+i386_fetch_inferior_register (struct regcache *regcache,
+			      windows_thread_info *th, int r)
+{
   char *context_offset = windows_process.with_context (th, [&] (auto *context)
     {
-      return (char *) context + mappings[r];
+      return get_context_reg_ptr (context, r);
     });
 
   /* GDB treats some registers as 32-bit, where they are in fact only
@@ -514,17 +536,9 @@ static void
 i386_store_inferior_register (struct regcache *regcache,
 			      windows_thread_info *th, int r)
 {
-  const int *mappings;
-#ifdef __x86_64__
-  if (!windows_process.wow64_process)
-    mappings = amd64_mappings;
-  else
-#endif
-    mappings = i386_mappings;
-
   char *context_offset = windows_process.with_context (th, [&] (auto *context)
     {
-      return (char *) context + mappings[r];
+      return get_context_reg_ptr (context, r);
     });
 
   /* GDB treats some registers as 32-bit, where they are in fact only
-- 
2.55.0


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

* [PATCH v4 5/9] Windows gdb: Prepare XState functions
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
                     ` (2 preceding siblings ...)
  2026-09-30 15:11   ` [PATCH v4 4/9] Windows gdb: Refactor getting pointer to register inside context Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 6/9] Windows gdb: Get available XState features Hannes Domani
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

These functions will then be used to access the XState registers.

Approved-By: Tom Tromey <tom@tromey.com>
---
v3: no changes
v4: no changes
---
 gdb/nat/windows-nat.c |  31 +++++++++++
 gdb/nat/windows-nat.h | 116 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+)

diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 974b1d3535b..8f91e755334 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -73,6 +73,19 @@ InitializeProcThreadAttributeList_ftype *InitializeProcThreadAttributeList;
 UpdateProcThreadAttribute_ftype *UpdateProcThreadAttribute;
 DeleteProcThreadAttributeList_ftype *DeleteProcThreadAttributeList;
 
+#if defined __i386__ || defined __x86_64__
+GetEnabledXStateFeatures_ftype *GetEnabledXStateFeatures;
+InitializeContext_ftype *InitializeContext;
+GetXStateFeaturesMask_ftype *GetXStateFeaturesMask;
+SetXStateFeaturesMask_ftype *SetXStateFeaturesMask;
+LocateXStateFeature_ftype *LocateXStateFeature;
+#ifdef __x86_64__
+RtlGetExtendedFeaturesMask_ftype *RtlGetExtendedFeaturesMask;
+RtlSetExtendedFeaturesMask_ftype *RtlSetExtendedFeaturesMask;
+RtlLocateExtendedFeature_ftype *RtlLocateExtendedFeature;
+#endif
+#endif
+
 /* Note that 'debug_events' must be locally defined in the relevant
    functions.  */
 #define DEBUG_EVENTS(fmt, ...) \
@@ -1194,6 +1207,14 @@ initialize_loadable ()
       GPA (hm, InitializeProcThreadAttributeList);
       GPA (hm, UpdateProcThreadAttribute);
       GPA (hm, DeleteProcThreadAttributeList);
+
+#if defined __i386__ || defined __x86_64__
+      GPA (hm, GetEnabledXStateFeatures);
+      GPA (hm, InitializeContext);
+      GPA (hm, GetXStateFeaturesMask);
+      GPA (hm, SetXStateFeaturesMask);
+      GPA (hm, LocateXStateFeature);
+#endif
     }
 
   /* Set variables to dummy versions of these processes if the function
@@ -1259,6 +1280,16 @@ initialize_loadable ()
 	GPA (hm, GetThreadDescription);
     }
 
+#ifdef __x86_64__
+  hm = LoadLibrary (TEXT ("ntdll.dll"));
+  if (hm)
+    {
+      GPA (hm, RtlGetExtendedFeaturesMask);
+      GPA (hm, RtlSetExtendedFeaturesMask);
+      GPA (hm, RtlLocateExtendedFeature);
+    }
+#endif
+
 #undef GPA
 
   return result;
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index c153ad2c82c..511f5605384 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -35,6 +35,9 @@
 #define CONTEXT_EXTENDED_REGISTERS 0
 #endif
 
+#define CONTEXT_EXTENDED_REGISTERS_FLAG	0x20
+#define CONTEXT_XSTATE_FLAG		0x40
+
 namespace windows_nat
 {
 
@@ -445,6 +448,14 @@ extern BOOL create_process (const wchar_t *image, wchar_t *command_line,
 #define InitializeProcThreadAttributeList dyn_InitializeProcThreadAttributeList
 #define UpdateProcThreadAttribute dyn_UpdateProcThreadAttribute
 #define DeleteProcThreadAttributeList dyn_DeleteProcThreadAttributeList
+#define GetEnabledXStateFeatures	dyn_GetEnabledXStateFeatures
+#define InitializeContext		dyn_InitializeContext
+#define GetXStateFeaturesMask		dyn_GetXStateFeaturesMask
+#define SetXStateFeaturesMask		dyn_SetXStateFeaturesMask
+#define LocateXStateFeature		dyn_LocateXStateFeature
+#define RtlGetExtendedFeaturesMask	dyn_RtlGetExtendedFeaturesMask
+#define RtlSetExtendedFeaturesMask	dyn_RtlSetExtendedFeaturesMask
+#define RtlLocateExtendedFeature	dyn_RtlLocateExtendedFeature
 
 typedef BOOL WINAPI (AdjustTokenPrivileges_ftype) (HANDLE, BOOL,
 						   PTOKEN_PRIVILEGES,
@@ -539,6 +550,35 @@ extern DeleteProcThreadAttributeList_ftype *DeleteProcThreadAttributeList;
 
 extern bool disable_randomization_available ();
 
+#if defined __i386__ || defined __x86_64__
+typedef DWORD64 (WINAPI GetEnabledXStateFeatures_ftype) ();
+extern GetEnabledXStateFeatures_ftype *GetEnabledXStateFeatures;
+
+typedef BOOL (WINAPI InitializeContext_ftype) (PVOID, DWORD,
+					       PCONTEXT*, PDWORD);
+extern InitializeContext_ftype *InitializeContext;
+
+typedef BOOL (WINAPI GetXStateFeaturesMask_ftype) (PCONTEXT, PDWORD64);
+extern GetXStateFeaturesMask_ftype *GetXStateFeaturesMask;
+
+typedef BOOL (WINAPI SetXStateFeaturesMask_ftype) (PCONTEXT, DWORD64);
+extern SetXStateFeaturesMask_ftype *SetXStateFeaturesMask;
+
+typedef PVOID (WINAPI LocateXStateFeature_ftype) (PCONTEXT, DWORD, PDWORD);
+extern LocateXStateFeature_ftype *LocateXStateFeature;
+
+#ifdef __x86_64__
+typedef DWORD64 (WINAPI RtlGetExtendedFeaturesMask_ftype) (PVOID);
+extern RtlGetExtendedFeaturesMask_ftype *RtlGetExtendedFeaturesMask;
+
+typedef VOID (WINAPI RtlSetExtendedFeaturesMask_ftype) (PVOID, DWORD64);
+extern RtlSetExtendedFeaturesMask_ftype *RtlSetExtendedFeaturesMask;
+
+typedef PVOID (WINAPI RtlLocateExtendedFeature_ftype) (PVOID, DWORD, PDWORD);
+extern RtlLocateExtendedFeature_ftype *RtlLocateExtendedFeature;
+#endif
+#endif
+
 /* Helper classes to get the correct ContextFlags values based on the
    used type (CONTEXT or WOW64_CONTEXT).  */
 
@@ -604,16 +644,69 @@ enum_process_modules (CONTEXT *, HANDLE process,
   return EnumProcessModules (process, modules, size, needed);
 }
 
+#if defined __i386__ || defined __x86_64__
+static inline BOOL
+get_xstate_features_mask (CONTEXT *context, DWORD64 *mask)
+{
+  return GetXStateFeaturesMask (context, mask);
+}
+
+static inline BOOL
+set_xstate_features_mask (CONTEXT *context, DWORD64 mask)
+{
+  return SetXStateFeaturesMask (context, mask);
+}
+
+static inline PVOID
+locate_xstate_feature (CONTEXT *context, DWORD feature, DWORD *length)
+{
+  return LocateXStateFeature (context, feature, length);
+}
+#endif
+
 #ifdef __x86_64__
 static inline BOOL
 get_thread_context (HANDLE h, WOW64_CONTEXT *context)
 {
+  if ((context->ContextFlags & CONTEXT_XSTATE_FLAG) != 0)
+    {
+      /* Wow64GetThreadContext doesn't handle CONTEXT_EXTENDED_REGISTERS and
+	 CONTEXT_XSTATE combined correctly, but separate they work fine.  */
+      DWORD flags = context->ContextFlags;
+      context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS_FLAG;
+      BOOL ret = Wow64GetThreadContext (h, context);
+      context->ContextFlags = flags;
+      if (!ret)
+	return FALSE;
+
+      context->ContextFlags &= ~CONTEXT_XSTATE_FLAG;
+      ret = Wow64GetThreadContext (h, context);
+      context->ContextFlags = flags;
+      return ret;
+    }
+
   return Wow64GetThreadContext (h, context);
 }
 
 static inline BOOL
 set_thread_context (HANDLE h, WOW64_CONTEXT *context)
 {
+  if ((context->ContextFlags & CONTEXT_XSTATE_FLAG) != 0)
+    {
+      /* Same limitation as Wow64GetThreadContext above.  */
+      DWORD flags = context->ContextFlags;
+      context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS_FLAG;
+      BOOL ret = Wow64SetThreadContext (h, context);
+      context->ContextFlags = flags;
+      if (!ret)
+	return FALSE;
+
+      context->ContextFlags &= ~CONTEXT_XSTATE_FLAG;
+      ret = Wow64SetThreadContext (h, context);
+      context->ContextFlags = flags;
+      return ret;
+    }
+
   return Wow64SetThreadContext (h, context);
 }
 
@@ -631,6 +724,29 @@ enum_process_modules (WOW64_CONTEXT *, HANDLE process,
   return EnumProcessModulesEx (process, modules, size, needed,
 			       LIST_MODULES_32BIT);
 }
+
+static inline BOOL
+get_xstate_features_mask (WOW64_CONTEXT *context, DWORD64 *mask)
+{
+  /* Use lower level function, since there is no Wow64GetXStateFeaturesMask.  */
+  *mask = RtlGetExtendedFeaturesMask (context + 1);
+  return TRUE;
+}
+
+static inline BOOL
+set_xstate_features_mask (WOW64_CONTEXT *context, DWORD64 mask)
+{
+  /* Use lower level function, since there is no Wow64SetXStateFeaturesMask.  */
+  RtlSetExtendedFeaturesMask (context + 1, mask);
+  return TRUE;
+}
+
+static inline PVOID
+locate_xstate_feature (WOW64_CONTEXT *context, DWORD feature, DWORD *length)
+{
+  /* Use lower level function, since there is no Wow64LocateXStateFeature.  */
+  return RtlLocateExtendedFeature (context + 1, feature, length);
+}
 #endif
 
 /* This is available starting with Windows 10.  */
-- 
2.55.0


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

* [PATCH v4 6/9] Windows gdb: Get available XState features
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
                     ` (3 preceding siblings ...)
  2026-09-30 15:11   ` [PATCH v4 5/9] Windows gdb: Prepare XState functions Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 7/9] Windows gdb: Implement AVX register support Hannes Domani
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

Also prepares the thread context for the additional registers.

Approved-By: Tom Tromey <tom@tromey.com>
---
v2:
  - Remove PKRU from the implemented features mask
v3:
  - use throw_winerror_with_name instead of error
  - fix formatting and value of xstate_features
v4: no changes
---
 gdb/nat/windows-nat.c | 57 ++++++++++++++++++++++++++++++++++++++++++-
 gdb/nat/windows-nat.h |  5 ++++
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 8f91e755334..58be5368a79 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -20,6 +20,7 @@
 #include "gdbsupport/common-debug.h"
 #include "gdbsupport/gdb_signals.h"
 #include "gdbsupport/gdb_wait.h"
+#include "gdbsupport/x86-xstate.h"
 #include "target/target.h"
 
 #undef GetModuleFileNameEx
@@ -84,6 +85,8 @@ RtlGetExtendedFeaturesMask_ftype *RtlGetExtendedFeaturesMask;
 RtlSetExtendedFeaturesMask_ftype *RtlSetExtendedFeaturesMask;
 RtlLocateExtendedFeature_ftype *RtlLocateExtendedFeature;
 #endif
+
+DWORD64 xstate_features;
 #endif
 
 /* Note that 'debug_events' must be locally defined in the relevant
@@ -99,12 +102,41 @@ windows_thread_info::windows_thread_info (windows_process_info *proc_,
     h (h_),
     thread_local_base (tlb)
 {
+#if defined __i386__ || defined __x86_64__
+  if (xstate_features != 0)
+    {
+      DWORD context_flags = proc->with_context (nullptr, [] (auto *context)
+	{
+	  return WindowsContext<decltype(context)>::all;
+	});
+      context_flags |= CONTEXT_XSTATE_FLAG;
+      DWORD xstate_size = 0;
+      InitializeContext (nullptr, context_flags, nullptr, &xstate_size);
+      context_buffer.reset (xmalloc (xstate_size));
+      CONTEXT *c = nullptr;
+      if (!InitializeContext (context_buffer.get (),
+			      context_flags, &c, &xstate_size))
+	{
+	  unsigned err = (unsigned) GetLastError ();
+	  throw_winerror_with_name (_("InitializeContext failed"), err);
+	}
 #ifdef __x86_64__
-  if (proc->wow64_process)
+      /* InitializeContext actually initializes a WOW64_CONTEXT when
+	 context_flags contains a WOW64_CONTEXT_* value, so a cast is needed.
+	 */
+      if (proc->wow64_process)
+	wow64_context = (WOW64_CONTEXT *) c;
+      else
+#endif
+	context = c;
+    }
+#ifdef __x86_64__
+  else if (proc->wow64_process)
     {
       context_buffer.reset (xmalloc (sizeof (WOW64_CONTEXT)));
       wow64_context = (WOW64_CONTEXT *) context_buffer.get ();
     }
+#endif
   else
 #endif
     {
@@ -1292,6 +1324,29 @@ initialize_loadable ()
 
 #undef GPA
 
+#if defined __i386__ || defined __x86_64__
+  if (GetEnabledXStateFeatures != nullptr
+      && InitializeContext != nullptr
+      && GetXStateFeaturesMask != nullptr
+      && SetXStateFeaturesMask != nullptr
+      && LocateXStateFeature != nullptr
+#ifdef __x86_64__
+      && RtlGetExtendedFeaturesMask != nullptr
+      && RtlSetExtendedFeaturesMask != nullptr
+      && RtlLocateExtendedFeature != nullptr
+#endif
+  )
+    {
+      /* Available XState features masked with implemented features.  */
+      xstate_features = (GetEnabledXStateFeatures ()
+			 & X86_XSTATE_SSE_MASK);
+      /* The extended XState functions are only needed if the available
+	 features exceed SSE.  */
+      if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
+	xstate_features = 0;
+    }
+#endif
+
   return result;
 }
 
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index 511f5605384..a7d4af84e13 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -749,6 +749,11 @@ locate_xstate_feature (WOW64_CONTEXT *context, DWORD feature, DWORD *length)
 }
 #endif
 
+#if defined __i386__ || defined __x86_64__
+/* Available XState features.  */
+extern DWORD64 xstate_features;
+#endif
+
 /* This is available starting with Windows 10.  */
 #ifndef DBG_REPLY_LATER
 # define DBG_REPLY_LATER 0x40010001L
-- 
2.55.0


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

* [PATCH v4 7/9] Windows gdb: Implement AVX register support
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
                     ` (4 preceding siblings ...)
  2026-09-30 15:11   ` [PATCH v4 6/9] Windows gdb: Get available XState features Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  2026-10-05 14:09     ` Rohr, Stephan
  2026-09-30 15:11   ` [PATCH v4 8/9] Windows gdb: Implement AVX-512 " Hannes Domani
  2026-09-30 15:11   ` [PATCH v4 9/9] Windows gdbserver: Remove win32_target_ops "num_regs" method Hannes Domani
  7 siblings, 1 reply; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches

This adds support for the Intel AVX registers on Windows.
It enables accessing registers $ymm0 - $ymm15 where they are available.

After this patch gdb.arch/i386-avx.exp passes on windows.
---
v3:
  - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
v4:
  - fixed $ymm15 in NEWS
  - Add common function windows_thread_info::zero_xstate_features,
    and fix maximum supported feature in for-loop
  - Add check for enabled xstate_features in get_context_reg_ptr of
    x86-windows-nat.c
  - Move amd64 variable in get_context_reg_ptr of win32-i386-low.cc
  - Changed all NULL to nullptr
  - Don't remove 'r == 0' from child_store_inferior_registers
---
 gdb/NEWS                    |  3 +++
 gdb/nat/windows-nat.c       | 36 +++++++++++++++++++++++++-
 gdb/nat/windows-nat.h       |  6 +++++
 gdb/x86-windows-nat.c       | 51 ++++++++++++++++++++++++++++++++++---
 gdbserver/win32-i386-low.cc | 47 +++++++++++++++++++++++++++++-----
 gdbserver/win32-low.cc      | 15 +++++++----
 6 files changed, 143 insertions(+), 15 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 5d0c4745653..da4bc811c3a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -194,6 +194,9 @@ info locals
   intent to remove it in a future release.
   The s390 64-bit target (s390x-*) remains supported.
 
+* Support for Intel AVX registers on Windows.
+  Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
+
 * Configure changes
 
 ** --with-babeltrace has been removed.  The babeltrace library was
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 58be5368a79..cd3c827a5d5 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -271,6 +271,40 @@ windows_thread_info::xfer_siginfo (gdb_byte *readbuf,
   return true;
 }
 
+#if defined __i386__ || defined __x86_64__
+/* See nat/windows-nat.h.  */
+
+void
+windows_thread_info::zero_xstate_features ()
+{
+  if (xstate_features == 0)
+    return;
+
+  proc->with_context (this, [] (auto *context)
+    {
+      DWORD64 features = 0;
+      if (!get_xstate_features_mask (context, &features))
+	return;
+
+      DWORD64 zeroed_features = xstate_features & ~features;
+      if (zeroed_features == 0)
+	return;
+
+      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
+	{
+	  DWORD64 flag = 1ULL << f;
+	  if ((zeroed_features & flag) != 0)
+	    {
+	      DWORD size = 0;
+	      void *loc = locate_xstate_feature (context, f, &size);
+	      if (loc != nullptr && size > 0)
+		memset (loc, 0, size);
+	    }
+	}
+    });
+}
+#endif
+
 /* Try to determine the executable filename.
 
    EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
@@ -1339,7 +1373,7 @@ initialize_loadable ()
     {
       /* Available XState features masked with implemented features.  */
       xstate_features = (GetEnabledXStateFeatures ()
-			 & X86_XSTATE_SSE_MASK);
+			 & X86_XSTATE_AVX_MASK);
       /* The extended XState functions are only needed if the available
 	 features exceed SSE.  */
       if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index a7d4af84e13..4cd75cb6a0e 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -90,6 +90,12 @@ struct windows_thread_info
 		     ULONGEST offset, ULONGEST len,
 		     ULONGEST *xfered_len);
 
+#if defined __i386__ || defined __x86_64__
+  /* Zero all XState feature areas that were not provided by
+     GetThreadContext.  */
+  void zero_xstate_features ();
+#endif
+
   /* The process this thread belongs to.  */
   windows_process_info *const proc;
 
diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
index 3af5ef4dae0..1e44a45171c 100644
--- a/gdb/x86-windows-nat.c
+++ b/gdb/x86-windows-nat.c
@@ -27,6 +27,9 @@
 
 #include "i386-tdep.h"
 #include "i387-tdep.h"
+#ifdef __x86_64__
+#include "amd64-tdep.h"
+#endif
 
 using namespace windows_nat;
 
@@ -70,6 +73,8 @@ struct x86_windows_nat_target final : public x86_nat_target<windows_nat_target>
 			   windows_thread_info *th, int r) override;
 
   bool is_sw_breakpoint (const EXCEPTION_RECORD *er) const override;
+
+  const struct target_desc *read_description () override;
 };
 
 /* The current process.  */
@@ -109,7 +114,14 @@ x86_windows_per_inferior::fill_thread_context (windows_thread_info *th)
       if (context->ContextFlags == 0)
 	{
 	  context->ContextFlags = WindowsContext<decltype(context)>::all;
+	  if (xstate_features != 0)
+	    {
+	      context->ContextFlags |= CONTEXT_XSTATE_FLAG;
+	      set_xstate_features_mask (context, xstate_features);
+	    }
 	  CHECK (get_thread_context (th->h, context));
+
+	  th->zero_xstate_features ();
 	}
     });
 }
@@ -198,6 +210,14 @@ x86_windows_nat_target::thread_context_continue (windows_thread_info *th,
 	  if (GetExitCodeThread (th->h, &ec)
 	      && ec == STILL_ACTIVE)
 	    {
+	      DWORD debug_registers = WindowsContext<decltype(context)>::debug;
+	      if (xstate_features != 0
+		  && (context->ContextFlags & ~debug_registers) != 0)
+		{
+		  context->ContextFlags |= CONTEXT_XSTATE_FLAG;
+		  set_xstate_features_mask (context, xstate_features);
+		}
+
 	      BOOL status = set_thread_context (th->h, context);
 
 	      if (!killed)
@@ -227,7 +247,7 @@ x86_windows_nat_target::thread_context_step (windows_thread_info *th,
 
 template<typename Context>
 static char *
-get_context_reg_ptr (Context *context, int r)
+get_context_reg_ptr (Context *context, int r, i386_gdbarch_tdep *tdep)
 {
   const int *mappings;
   int mappings_count;
@@ -247,6 +267,14 @@ get_context_reg_ptr (Context *context, int r)
   char *context_offset;
   if (r < mappings_count)
     context_offset = (char *) context + mappings[r];
+  else if ((xstate_features & X86_XSTATE_AVX) != 0
+	   && I387_YMM0H_REGNUM (tdep) > 0 && r >= I387_YMM0H_REGNUM (tdep)
+	   && r < I387_YMMENDH_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_AVX_ID, nullptr);
+      context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
+    }
   else
     gdb_assert_not_reached ("invalid register number %d", r);
 
@@ -267,7 +295,7 @@ x86_windows_nat_target::fetch_one_register (struct regcache *regcache,
   char *context_offset
     = x86_windows_process.with_context (th, [&] (auto *context)
     {
-      return get_context_reg_ptr (context, r);
+      return get_context_reg_ptr (context, r, tdep);
     });
 
   gdb_assert (!gdbarch_read_pc_p (gdbarch));
@@ -333,7 +361,7 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache,
     = x86_windows_process.with_context (th, [&] (auto *context)
     {
       gdb_assert (context->ContextFlags != 0);
-      return get_context_reg_ptr (context, r);
+      return get_context_reg_ptr (context, r, tdep);
     });
 
   /* GDB treats some registers as 32-bit, where they are in fact only
@@ -368,6 +396,23 @@ x86_windows_nat_target::is_sw_breakpoint (const EXCEPTION_RECORD *er) const
 	  || er->ExceptionCode == STATUS_WX86_BREAKPOINT);
 }
 
+const struct target_desc *
+x86_windows_nat_target::read_description ()
+{
+  if (inferior_ptid == null_ptid)
+    return this->beneath ()->read_description ();
+
+  if (xstate_features == 0)
+    return nullptr;
+
+#ifdef __x86_64__
+  if (!x86_windows_process.wow64_process)
+    return amd64_target_description (xstate_features, false);
+  else
+#endif
+    return i386_target_description (xstate_features, false);
+}
+
 /* Hardware watchpoint support, adapted from go32-nat.c code.  */
 
 /* Pass the address ADDR to the inferior in the I'th debug register.
diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
index b77f6adc6ed..1a45b15e0cf 100644
--- a/gdbserver/win32-i386-low.cc
+++ b/gdbserver/win32-i386-low.cc
@@ -253,6 +253,11 @@ i386_get_thread_context (windows_thread_info *th)
 			       | WindowsContext<decltype(context)>::floating
 			       | WindowsContext<decltype(context)>::debug
 			       | extended_registers);
+      if (xstate_features != 0)
+	{
+	  context->ContextFlags |= CONTEXT_XSTATE_FLAG;
+	  set_xstate_features_mask (context, xstate_features);
+	}
 
       BOOL ret = get_thread_context (th->h, context);
       if (!ret)
@@ -267,6 +272,8 @@ i386_get_thread_context (windows_thread_info *th)
 
 	  error (_("GetThreadContext failure %ld\n"), (long) e);
 	}
+
+      th->zero_xstate_features ();
     });
 }
 
@@ -292,6 +299,17 @@ i386_prepare_to_resume (windows_thread_info *th)
 
       th->debug_registers_changed = false;
     }
+
+  windows_process.with_context (th, [&] (auto *context)
+    {
+      DWORD debug_registers = WindowsContext<decltype(context)>::debug;
+      if (xstate_features != 0
+	  && (context->ContextFlags & ~debug_registers) != 0)
+	{
+	  context->ContextFlags |= CONTEXT_XSTATE_FLAG;
+	  set_xstate_features_mask (context, xstate_features);
+	}
+    });
 }
 
 static void
@@ -477,26 +495,40 @@ is_segment_register (int r)
 
 template<typename Context>
 static char *
-get_context_reg_ptr (Context *context, int r)
+get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)
 {
   const int *mappings;
   int mappings_count;
+  bool amd64;
 #ifdef __x86_64__
   if (!windows_process.wow64_process)
     {
       mappings = amd64_mappings;
       mappings_count = sizeof (amd64_mappings) / sizeof (amd64_mappings[0]);
+      amd64 = true;
     }
   else
 #endif
     {
       mappings = i386_mappings;
       mappings_count = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
+      amd64 = false;
     }
 
+  int ymm0h_regnum;
+  const int num_xmm_registers = amd64 ? 16 : 8;
+
   char *context_offset;
   if (r < mappings_count)
     context_offset = (char *) context + mappings[r];
+  else if ((xstate_features & X86_XSTATE_AVX) != 0
+	   && r >= (ymm0h_regnum = find_regno (tdesc, "ymm0h"))
+	   && r < ymm0h_regnum + num_xmm_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_AVX_ID, nullptr);
+      context_offset += 16 * (r - ymm0h_regnum);
+    }
   else
     gdb_assert_not_reached ("invalid register number %d", r);
 
@@ -510,7 +542,7 @@ i386_fetch_inferior_register (struct regcache *regcache,
 {
   char *context_offset = windows_process.with_context (th, [&] (auto *context)
     {
-      return get_context_reg_ptr (context, r);
+      return get_context_reg_ptr (context, r, regcache->tdesc);
     });
 
   /* GDB treats some registers as 32-bit, where they are in fact only
@@ -538,7 +570,7 @@ i386_store_inferior_register (struct regcache *regcache,
 {
   char *context_offset = windows_process.with_context (th, [&] (auto *context)
     {
-      return get_context_reg_ptr (context, r);
+      return get_context_reg_ptr (context, r, regcache->tdesc);
     });
 
   /* GDB treats some registers as 32-bit, where they are in fact only
@@ -571,14 +603,17 @@ i386_arch_setup (void)
 {
  target_desc_up tdesc;
 
+  DWORD64 xcr0 = xstate_features;
+  if (xcr0 == 0)
+    xcr0 = X86_XSTATE_SSE_MASK;
+
 #ifdef __x86_64__
-  tdesc = amd64_create_target_description (X86_XSTATE_SSE_MASK, false,
-					   false, false);
+  tdesc = amd64_create_target_description (xcr0, false, false, false);
   init_target_desc (tdesc.get (), amd64_expedite_regs, WINDOWS_OSABI);
   win32_tdesc = std::move (tdesc);
 #endif
 
-  tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false, false);
+  tdesc = i386_create_target_description (xcr0, false, false);
   init_target_desc (tdesc.get (), i386_expedite_regs, WINDOWS_OSABI);
 #ifdef __x86_64__
   wow64_win32_tdesc = std::move (tdesc);
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 1103a802db7..3e80405f651 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -33,6 +33,7 @@
 #include <process.h>
 #include "gdbsupport/gdb_tilde_expand.h"
 #include "gdbsupport/common-inferior.h"
+#include "tdesc.h"
 
 using namespace windows_nat;
 
@@ -427,8 +428,9 @@ child_fetch_inferior_registers (struct regcache *regcache, int r)
   int regno;
   windows_thread_info *th = windows_process.find_thread (current_thread->id);
   win32_require_context (th);
-  if (r == -1 || r > NUM_REGS)
-    child_fetch_inferior_registers (regcache, NUM_REGS);
+  if (r == -1)
+    child_fetch_inferior_registers (regcache,
+				    regcache->tdesc->reg_defs.size ());
   else
     for (regno = 0; regno < r; regno++)
       (*the_low_target.fetch_inferior_register) (regcache, th, regno);
@@ -442,8 +444,9 @@ child_store_inferior_registers (struct regcache *regcache, int r)
   int regno;
   windows_thread_info *th = windows_process.find_thread (current_thread->id);
   win32_require_context (th);
-  if (r == -1 || r == 0 || r > NUM_REGS)
-    child_store_inferior_registers (regcache, NUM_REGS);
+  if (r == -1 || r == 0)
+    child_store_inferior_registers (regcache,
+				    regcache->tdesc->reg_defs.size ());
   else
     for (regno = 0; regno < r; regno++)
       (*the_low_target.store_inferior_register) (regcache, th, regno);
@@ -1347,7 +1350,9 @@ void
 initialize_low (void)
 {
   set_target_ops (&the_win32_target);
-  the_low_target.arch_setup ();
 
   initialize_loadable ();
+  /* Has to be done after initialize_loadable, because it uses the xstate
+     functions if available.  */
+  the_low_target.arch_setup ();
 }
-- 
2.55.0


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

* [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
                     ` (5 preceding siblings ...)
  2026-09-30 15:11   ` [PATCH v4 7/9] Windows gdb: Implement AVX register support Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  2026-10-05 14:08     ` Rohr, Stephan
  2026-09-30 15:11   ` [PATCH v4 9/9] Windows gdbserver: Remove win32_target_ops "num_regs" method Hannes Domani
  7 siblings, 1 reply; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches

Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for Linux,
this patch adds support for the Intel AVX-512 registers for 32 and 64-bit
mode on Windows.
It enables accessing registers $ymm0 - $ymm31, $zmm0 - $zmm31, and
$k0 - $k7 where they are available.

After this patch gdb.arch/i386-avx512.exp passes on windows.
---
v3:
  - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
v4:
  - Add reference to equivalent Linux commit in commit message
  - Add check for enabled xstate_features in get_context_reg_ptr of
    x86-windows-nat.c
  - Changed all NULL to nullptr
---
 gdb/NEWS                    |  4 +++-
 gdb/nat/windows-nat.c       |  4 ++--
 gdb/x86-windows-nat.c       | 40 +++++++++++++++++++++++++++++++
 gdbserver/win32-i386-low.cc | 48 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 92 insertions(+), 4 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index da4bc811c3a..704e6a7c8ba 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -195,7 +195,9 @@ info locals
   The s390 64-bit target (s390x-*) remains supported.
 
 * Support for Intel AVX registers on Windows.
-  Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
+  Support displaying and modifying Intel AVX registers $ymm0 - $ymm31.
+  Support displaying and modifying Intel AVX-512 registers $zmm0 - $zmm31
+  and $k0 - $k7.
 
 * Configure changes
 
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index cd3c827a5d5..3940465d06b 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -290,7 +290,7 @@ windows_thread_info::zero_xstate_features ()
       if (zeroed_features == 0)
 	return;
 
-      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
+      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_ZMM_ID; f++)
 	{
 	  DWORD64 flag = 1ULL << f;
 	  if ((zeroed_features & flag) != 0)
@@ -1373,7 +1373,7 @@ initialize_loadable ()
     {
       /* Available XState features masked with implemented features.  */
       xstate_features = (GetEnabledXStateFeatures ()
-			 & X86_XSTATE_AVX_MASK);
+			 & X86_XSTATE_AVX_AVX512_MASK);
       /* The extended XState functions are only needed if the available
 	 features exceed SSE.  */
       if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
index 1e44a45171c..afc71b4ef61 100644
--- a/gdb/x86-windows-nat.c
+++ b/gdb/x86-windows-nat.c
@@ -275,6 +275,46 @@ get_context_reg_ptr (Context *context, int r, i386_gdbarch_tdep *tdep)
 	(context, X86_XSTATE_AVX_ID, nullptr);
       context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
     }
+  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
+	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >= I387_ZMM0H_REGNUM (tdep)
+	   && r < I387_ZMM16H_REGNUM (tdep) && r < I387_ZMMENDH_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_H_ID, nullptr);
+      context_offset += 32 * (r - I387_ZMM0H_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >= I387_ZMM16H_REGNUM (tdep)
+	   && r < I387_ZMMENDH_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 32 + 64 * (r - I387_ZMM16H_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_K) != 0
+	   && I387_K0_REGNUM (tdep) > 0 && r >= I387_K0_REGNUM (tdep)
+	   && r < I387_KEND_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_K_ID, nullptr);
+      context_offset += 8 * (r - I387_K0_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && I387_YMM16H_REGNUM (tdep) > 0 && r >= I387_YMM16H_REGNUM (tdep)
+	   && r < I387_YMMH_AVX512_END_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 16 + 64 * (r - I387_YMM16H_REGNUM (tdep));
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && I387_XMM16_REGNUM (tdep) > 0 && r >= I387_XMM16_REGNUM (tdep)
+	   && r < I387_XMM_AVX512_END_REGNUM (tdep))
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 64 * (r - I387_XMM16_REGNUM (tdep));
+    }
   else
     gdb_assert_not_reached ("invalid register number %d", r);
 
diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
index 1a45b15e0cf..8c62787a31b 100644
--- a/gdbserver/win32-i386-low.cc
+++ b/gdbserver/win32-i386-low.cc
@@ -515,8 +515,11 @@ get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)
       amd64 = false;
     }
 
-  int ymm0h_regnum;
+  int ymm0h_regnum, zmm0h_regnum, k0_regnum;
+  int xmm16_regnum, ymm16h_regnum, zmm16h_regnum;
   const int num_xmm_registers = amd64 ? 16 : 8;
+  const int num_zmm_high_registers = amd64 ? 16 : 0;
+  const int num_avx512_k_registers = 8;
 
   char *context_offset;
   if (r < mappings_count)
@@ -529,6 +532,49 @@ get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)
 	(context, X86_XSTATE_AVX_ID, nullptr);
       context_offset += 16 * (r - ymm0h_regnum);
     }
+  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
+	   && r >= (zmm0h_regnum = find_regno (tdesc, "zmm0h"))
+	   && r < zmm0h_regnum + num_xmm_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_H_ID, nullptr);
+      context_offset += 32 * (r - zmm0h_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && num_zmm_high_registers != 0
+	   && r >= (zmm16h_regnum = find_regno (tdesc, "zmm16h"))
+	   && r < zmm16h_regnum + num_zmm_high_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 32 + 64 * (r - zmm16h_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_K) != 0
+	   && r >= (k0_regnum = find_regno (tdesc, "k0"))
+	   && r < k0_regnum + num_avx512_k_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_K_ID, nullptr);
+      context_offset += 8 * (r - k0_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && num_zmm_high_registers != 0
+	   && r >= (ymm16h_regnum = find_regno (tdesc, "ymm16h"))
+	   && r < ymm16h_regnum + num_zmm_high_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 16 + 64 * (r - ymm16h_regnum);
+    }
+  else if ((xstate_features & X86_XSTATE_ZMM) != 0
+	   && num_zmm_high_registers != 0
+	   && r >= (xmm16_regnum = find_regno (tdesc, "xmm16"))
+	   && r < xmm16_regnum + num_zmm_high_registers)
+    {
+      context_offset = (char *) locate_xstate_feature
+	(context, X86_XSTATE_ZMM_ID, nullptr);
+      context_offset += 64 * (r - xmm16_regnum);
+    }
   else
     gdb_assert_not_reached ("invalid register number %d", r);
 
-- 
2.55.0


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

* [PATCH v4 9/9] Windows gdbserver: Remove win32_target_ops "num_regs" method
  2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
                     ` (6 preceding siblings ...)
  2026-09-30 15:11   ` [PATCH v4 8/9] Windows gdb: Implement AVX-512 " Hannes Domani
@ 2026-09-30 15:11   ` Hannes Domani
  7 siblings, 0 replies; 18+ messages in thread
From: Hannes Domani @ 2026-09-30 15:11 UTC (permalink / raw)
  To: gdb-patches

It's no longer used since the AVX patch.
---
v4: this patch didn't exist before
---
 gdbserver/win32-aarch64-low.cc | 10 ----------
 gdbserver/win32-i386-low.cc    | 16 ----------------
 gdbserver/win32-low.cc         |  2 --
 gdbserver/win32-low.h          |  3 ---
 4 files changed, 31 deletions(-)

diff --git a/gdbserver/win32-aarch64-low.cc b/gdbserver/win32-aarch64-low.cc
index e94548b6fef..dfcb940f3e3 100644
--- a/gdbserver/win32-aarch64-low.cc
+++ b/gdbserver/win32-aarch64-low.cc
@@ -394,15 +394,6 @@ aarch64_arch_setup ()
   aarch64_tdesc = std::move (tdesc);
 }
 
-/* Implement win32_target_ops "num_regs" method.  */
-
-static int
-aarch64_win32_num_regs ()
-{
-  int num_regs = sizeof (aarch64_mappings) / sizeof (aarch64_mappings[0]);
-  return num_regs;
-}
-
 /* Implement win32_target_ops "get_pc" method.  */
 
 static CORE_ADDR
@@ -438,7 +429,6 @@ aarch64_is_sw_breakpoint (const EXCEPTION_RECORD *er)
 
 struct win32_target_ops the_low_target = {
   aarch64_arch_setup,
-  aarch64_win32_num_regs,
   aarch64_initial_stuff,
   aarch64_get_thread_context,
   aarch64_prepare_to_resume,
diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
index 8c62787a31b..e35fcbc3da1 100644
--- a/gdbserver/win32-i386-low.cc
+++ b/gdbserver/win32-i386-low.cc
@@ -668,21 +668,6 @@ i386_arch_setup (void)
 #endif
 }
 
-/* Implement win32_target_ops "num_regs" method.  */
-
-static int
-i386_win32_num_regs (void)
-{
-  int num_regs;
-#ifdef __x86_64__
-  if (!windows_process.wow64_process)
-    num_regs = sizeof (amd64_mappings) / sizeof (amd64_mappings[0]);
-  else
-#endif
-    num_regs = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
-  return num_regs;
-}
-
 /* Implement win32_target_ops "get_pc" method.  */
 
 static CORE_ADDR
@@ -738,7 +723,6 @@ i386_is_sw_breakpoint (const EXCEPTION_RECORD *er)
 
 struct win32_target_ops the_low_target = {
   i386_arch_setup,
-  i386_win32_num_regs,
   i386_initial_stuff,
   i386_get_thread_context,
   i386_prepare_to_resume,
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 3e80405f651..0d08a7e8915 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -62,8 +62,6 @@ gdbserver_windows_process windows_process;
 
 int using_threads = 1;
 
-#define NUM_REGS (the_low_target.num_regs ())
-
 /* The current debug event from WaitForDebugEvent.  */
 static ptid_t
 debug_event_ptid (DEBUG_EVENT *event)
diff --git a/gdbserver/win32-low.h b/gdbserver/win32-low.h
index dffa13e31f8..af12805dcfd 100644
--- a/gdbserver/win32-low.h
+++ b/gdbserver/win32-low.h
@@ -37,9 +37,6 @@ struct win32_target_ops
   /* Architecture-specific setup.  */
   void (*arch_setup) (void);
 
-  /* The number of target registers.  */
-  int (*num_regs) (void);
-
   /* Perform initializations on startup.  */
   void (*initial_stuff) (process_info *proc);
 
-- 
2.55.0


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

* RE: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
  2026-09-30 15:11   ` [PATCH v4 8/9] Windows gdb: Implement AVX-512 " Hannes Domani
@ 2026-10-05 14:08     ` Rohr, Stephan
  2026-10-09 14:36       ` Hannes Domani
  0 siblings, 1 reply; 18+ messages in thread
From: Rohr, Stephan @ 2026-10-05 14:08 UTC (permalink / raw)
  To: Hannes Domani, gdb-patches; +Cc: Joos, Christina

Hi Hanns,

also here, some minor findings below.

Thanks
Stephan

> -----Original Message-----
> From: Hannes Domani <ssbssa@yahoo.de>
> Sent: Wednesday, 30 September 2026 17:12
> To: gdb-patches@sourceware.org
> Subject: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
> 
> Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for Linux,

Maybe name the commit title instead of the hash.  Not sure what is best
practice for this.

> this patch adds support for the Intel AVX-512 registers for 32 and 64-bit
> mode on Windows.
> It enables accessing registers $ymm0 - $ymm31, $zmm0 - $zmm31, and
> $k0 - $k7 where they are available.
> 

Wouldn't we want to mention "It enables accessing registers
$ymm16 - $ymm31 [..]" instead?

> After this patch gdb.arch/i386-avx512.exp passes on windows.
> ---
> v3:
>   - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
> v4:
>   - Add reference to equivalent Linux commit in commit message
>   - Add check for enabled xstate_features in get_context_reg_ptr of
>     x86-windows-nat.c
>   - Changed all NULL to nullptr
> ---
>  gdb/NEWS                    |  4 +++-
>  gdb/nat/windows-nat.c       |  4 ++--
>  gdb/x86-windows-nat.c       | 40 +++++++++++++++++++++++++++++++
>  gdbserver/win32-i386-low.cc | 48
> ++++++++++++++++++++++++++++++++++++-
>  4 files changed, 92 insertions(+), 4 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index da4bc811c3a..704e6a7c8ba 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -195,7 +195,9 @@ info locals
>    The s390 64-bit target (s390x-*) remains supported.
> 
>  * Support for Intel AVX registers on Windows.
> -  Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
> +  Support displaying and modifying Intel AVX registers $ymm0 - $ymm31.

AVX is limited to $ymm0 - $ymm15.  Maybe add another bullet
"Support for Intel AVX-512 registers on Windows." and list what's introduced
in this patch. 

> +  Support displaying and modifying Intel AVX-512 registers $zmm0 - $zmm31
> +  and $k0 - $k7.
> 
>  * Configure changes
> 
> diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
> index cd3c827a5d5..3940465d06b 100644
> --- a/gdb/nat/windows-nat.c
> +++ b/gdb/nat/windows-nat.c
> @@ -290,7 +290,7 @@ windows_thread_info::zero_xstate_features ()
>        if (zeroed_features == 0)
>  	return;
> 
> -      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
> +      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_ZMM_ID; f++)
>  	{
>  	  DWORD64 flag = 1ULL << f;
>  	  if ((zeroed_features & flag) != 0)
> @@ -1373,7 +1373,7 @@ initialize_loadable ()
>      {
>        /* Available XState features masked with implemented features.  */
>        xstate_features = (GetEnabledXStateFeatures ()
> -			 & X86_XSTATE_AVX_MASK);
> +			 & X86_XSTATE_AVX_AVX512_MASK);

I think it makes sense to add a check that bits X86_XSTATE_K, X86_XSTATE_ZMM_H
and X86_XSTATE_ZMM are all set.  x86-xstate.h explicitly mentions
"AVX 512 adds three feature bits.  All three must be enabled.".  I know this is a
theoretical example but it doesn't hurt, e.g.,

if ((xstate_features & X86_XSTATE_AVX512) != X86_XSTATE_AVX512)
  xstate_features &= ~X86_XSTATE_AVX512;

>        /* The extended XState functions are only needed if the available
>  	 features exceed SSE.  */
>        if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
> diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
> index 1e44a45171c..afc71b4ef61 100644
> --- a/gdb/x86-windows-nat.c
> +++ b/gdb/x86-windows-nat.c
> @@ -275,6 +275,46 @@ get_context_reg_ptr (Context *context, int r,
> i386_gdbarch_tdep *tdep)
>  	(context, X86_XSTATE_AVX_ID, nullptr);
>        context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
>      }
> +  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> +	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> I387_ZMM0H_REGNUM (tdep)
> +	   && r < I387_ZMM16H_REGNUM (tdep) && r <
> I387_ZMMENDH_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_H_ID, nullptr);
> +      context_offset += 32 * (r - I387_ZMM0H_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> I387_ZMM16H_REGNUM (tdep)
> +	   && r < I387_ZMMENDH_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 32 + 64 * (r - I387_ZMM16H_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_K) != 0
> +	   && I387_K0_REGNUM (tdep) > 0 && r >= I387_K0_REGNUM (tdep)
> +	   && r < I387_KEND_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_K_ID, nullptr);
> +      context_offset += 8 * (r - I387_K0_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && I387_YMM16H_REGNUM (tdep) > 0 && r >=
> I387_YMM16H_REGNUM (tdep)
> +	   && r < I387_YMMH_AVX512_END_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 16 + 64 * (r - I387_YMM16H_REGNUM (tdep));
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && I387_XMM16_REGNUM (tdep) > 0 && r >=
> I387_XMM16_REGNUM (tdep)
> +	   && r < I387_XMM_AVX512_END_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 64 * (r - I387_XMM16_REGNUM (tdep));
> +    }
>    else
>      gdb_assert_not_reached ("invalid register number %d", r);
> 
> diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
> index 1a45b15e0cf..8c62787a31b 100644
> --- a/gdbserver/win32-i386-low.cc
> +++ b/gdbserver/win32-i386-low.cc
> @@ -515,8 +515,11 @@ get_context_reg_ptr (Context *context, int r, const
> target_desc *tdesc)
>        amd64 = false;
>      }
> 
> -  int ymm0h_regnum;
> +  int ymm0h_regnum, zmm0h_regnum, k0_regnum;
> +  int xmm16_regnum, ymm16h_regnum, zmm16h_regnum;
>    const int num_xmm_registers = amd64 ? 16 : 8;
> +  const int num_zmm_high_registers = amd64 ? 16 : 0;
> +  const int num_avx512_k_registers = 8;
> 
>    char *context_offset;
>    if (r < mappings_count)
> @@ -529,6 +532,49 @@ get_context_reg_ptr (Context *context, int r, const
> target_desc *tdesc)
>  	(context, X86_XSTATE_AVX_ID, nullptr);
>        context_offset += 16 * (r - ymm0h_regnum);
>      }
> +  else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> +	   && r >= (zmm0h_regnum = find_regno (tdesc, "zmm0h"))
> +	   && r < zmm0h_regnum + num_xmm_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_H_ID, nullptr);
> +      context_offset += 32 * (r - zmm0h_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && num_zmm_high_registers != 0
> +	   && r >= (zmm16h_regnum = find_regno (tdesc, "zmm16h"))
> +	   && r < zmm16h_regnum + num_zmm_high_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 32 + 64 * (r - zmm16h_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_K) != 0
> +	   && r >= (k0_regnum = find_regno (tdesc, "k0"))
> +	   && r < k0_regnum + num_avx512_k_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_K_ID, nullptr);
> +      context_offset += 8 * (r - k0_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && num_zmm_high_registers != 0
> +	   && r >= (ymm16h_regnum = find_regno (tdesc, "ymm16h"))
> +	   && r < ymm16h_regnum + num_zmm_high_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 16 + 64 * (r - ymm16h_regnum);
> +    }
> +  else if ((xstate_features & X86_XSTATE_ZMM) != 0
> +	   && num_zmm_high_registers != 0
> +	   && r >= (xmm16_regnum = find_regno (tdesc, "xmm16"))
> +	   && r < xmm16_regnum + num_zmm_high_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_ZMM_ID, nullptr);
> +      context_offset += 64 * (r - xmm16_regnum);
> +    }
>    else
>      gdb_assert_not_reached ("invalid register number %d", r);
> 
> --
> 2.55.0

________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* RE: [PATCH v4 7/9] Windows gdb: Implement AVX register support
  2026-09-30 15:11   ` [PATCH v4 7/9] Windows gdb: Implement AVX register support Hannes Domani
@ 2026-10-05 14:09     ` Rohr, Stephan
  2026-10-09 14:30       ` Hannes Domani
  0 siblings, 1 reply; 18+ messages in thread
From: Rohr, Stephan @ 2026-10-05 14:09 UTC (permalink / raw)
  To: Hannes Domani, gdb-patches; +Cc: Joos, Christina

Hi Hannes,

some minor findings below.

With those fixed.

Reviewed-By: Rohr, Stephan <stephan.rohr@intel.com>

Thanks
Stephan

> -----Original Message-----
> From: Hannes Domani <ssbssa@yahoo.de>
> Sent: Wednesday, 30 September 2026 17:12
> To: gdb-patches@sourceware.org
> Subject: [PATCH v4 7/9] Windows gdb: Implement AVX register support
> 
> This adds support for the Intel AVX registers on Windows.
> It enables accessing registers $ymm0 - $ymm15 where they are available.
> 
> After this patch gdb.arch/i386-avx.exp passes on windows.
> ---
> v3:
>   - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
> v4:
>   - fixed $ymm15 in NEWS
>   - Add common function windows_thread_info::zero_xstate_features,
>     and fix maximum supported feature in for-loop
>   - Add check for enabled xstate_features in get_context_reg_ptr of
>     x86-windows-nat.c
>   - Move amd64 variable in get_context_reg_ptr of win32-i386-low.cc
>   - Changed all NULL to nullptr
>   - Don't remove 'r == 0' from child_store_inferior_registers
> ---
>  gdb/NEWS                    |  3 +++
>  gdb/nat/windows-nat.c       | 36 +++++++++++++++++++++++++-
>  gdb/nat/windows-nat.h       |  6 +++++
>  gdb/x86-windows-nat.c       | 51
> ++++++++++++++++++++++++++++++++++---
>  gdbserver/win32-i386-low.cc | 47 +++++++++++++++++++++++++++++-----
>  gdbserver/win32-low.cc      | 15 +++++++----
>  6 files changed, 143 insertions(+), 15 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 5d0c4745653..da4bc811c3a 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -194,6 +194,9 @@ info locals
>    intent to remove it in a future release.
>    The s390 64-bit target (s390x-*) remains supported.
> 
> +* Support for Intel AVX registers on Windows.
> +  Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
> +
>  * Configure changes
> 
>  ** --with-babeltrace has been removed.  The babeltrace library was
> diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
> index 58be5368a79..cd3c827a5d5 100644
> --- a/gdb/nat/windows-nat.c
> +++ b/gdb/nat/windows-nat.c
> @@ -271,6 +271,40 @@ windows_thread_info::xfer_siginfo (gdb_byte
> *readbuf,
>    return true;
>  }
> 
> +#if defined __i386__ || defined __x86_64__
> +/* See nat/windows-nat.h.  */
> +
> +void
> +windows_thread_info::zero_xstate_features ()
> +{
> +  if (xstate_features == 0)
> +    return;
> +
> +  proc->with_context (this, [] (auto *context)
> +    {
> +      DWORD64 features = 0;
> +      if (!get_xstate_features_mask (context, &features))
> +	return;
> +
> +      DWORD64 zeroed_features = xstate_features & ~features;
> +      if (zeroed_features == 0)
> +	return;
> +
> +      for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)

Start == End.

> +	{
> +	  DWORD64 flag = 1ULL << f;
> +	  if ((zeroed_features & flag) != 0)
> +	    {
> +	      DWORD size = 0;
> +	      void *loc = locate_xstate_feature (context, f, &size);
> +	      if (loc != nullptr && size > 0)
> +		memset (loc, 0, size);
> +	    }
> +	}
> +    });
> +}
> +#endif
> +
>  /* Try to determine the executable filename.
> 
>     EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
> @@ -1339,7 +1373,7 @@ initialize_loadable ()
>      {
>        /* Available XState features masked with implemented features.  */
>        xstate_features = (GetEnabledXStateFeatures ()
> -			 & X86_XSTATE_SSE_MASK);
> +			 & X86_XSTATE_AVX_MASK);
>        /* The extended XState functions are only needed if the available
>  	 features exceed SSE.  */
>        if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
> diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
> index a7d4af84e13..4cd75cb6a0e 100644
> --- a/gdb/nat/windows-nat.h
> +++ b/gdb/nat/windows-nat.h
> @@ -90,6 +90,12 @@ struct windows_thread_info
>  		     ULONGEST offset, ULONGEST len,
>  		     ULONGEST *xfered_len);
> 
> +#if defined __i386__ || defined __x86_64__
> +  /* Zero all XState feature areas that were not provided by
> +     GetThreadContext.  */
> +  void zero_xstate_features ();
> +#endif
> +
>    /* The process this thread belongs to.  */
>    windows_process_info *const proc;
> 
> diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
> index 3af5ef4dae0..1e44a45171c 100644
> --- a/gdb/x86-windows-nat.c
> +++ b/gdb/x86-windows-nat.c
> @@ -27,6 +27,9 @@
> 
>  #include "i386-tdep.h"
>  #include "i387-tdep.h"
> +#ifdef __x86_64__
> +#include "amd64-tdep.h"
> +#endif
> 
>  using namespace windows_nat;
> 
> @@ -70,6 +73,8 @@ struct x86_windows_nat_target final : public
> x86_nat_target<windows_nat_target>
>  			   windows_thread_info *th, int r) override;
> 
>    bool is_sw_breakpoint (const EXCEPTION_RECORD *er) const override;
> +
> +  const struct target_desc *read_description () override;
>  };
> 
>  /* The current process.  */
> @@ -109,7 +114,14 @@ x86_windows_per_inferior::fill_thread_context
> (windows_thread_info *th)
>        if (context->ContextFlags == 0)
>  	{
>  	  context->ContextFlags = WindowsContext<decltype(context)>::all;
> +	  if (xstate_features != 0)
> +	    {
> +	      context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> +	      set_xstate_features_mask (context, xstate_features);
> +	    }
>  	  CHECK (get_thread_context (th->h, context));
> +
> +	  th->zero_xstate_features ();
>  	}
>      });
>  }
> @@ -198,6 +210,14 @@
> x86_windows_nat_target::thread_context_continue (windows_thread_info
> *th,
>  	  if (GetExitCodeThread (th->h, &ec)
>  	      && ec == STILL_ACTIVE)
>  	    {
> +	      DWORD debug_registers =
> WindowsContext<decltype(context)>::debug;
> +	      if (xstate_features != 0
> +		  && (context->ContextFlags & ~debug_registers) != 0)
> +		{
> +		  context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> +		  set_xstate_features_mask (context, xstate_features);
> +		}
> +
>  	      BOOL status = set_thread_context (th->h, context);
> 
>  	      if (!killed)
> @@ -227,7 +247,7 @@ x86_windows_nat_target::thread_context_step
> (windows_thread_info *th,
> 
>  template<typename Context>
>  static char *
> -get_context_reg_ptr (Context *context, int r)
> +get_context_reg_ptr (Context *context, int r, i386_gdbarch_tdep *tdep)
>  {
>    const int *mappings;
>    int mappings_count;
> @@ -247,6 +267,14 @@ get_context_reg_ptr (Context *context, int r)
>    char *context_offset;
>    if (r < mappings_count)
>      context_offset = (char *) context + mappings[r];
> +  else if ((xstate_features & X86_XSTATE_AVX) != 0
> +	   && I387_YMM0H_REGNUM (tdep) > 0 && r >=
> I387_YMM0H_REGNUM (tdep)
> +	   && r < I387_YMMENDH_REGNUM (tdep))
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_AVX_ID, nullptr);
> +      context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
> +    }
>    else
>      gdb_assert_not_reached ("invalid register number %d", r);
> 
> @@ -267,7 +295,7 @@ x86_windows_nat_target::fetch_one_register (struct
> regcache *regcache,
>    char *context_offset
>      = x86_windows_process.with_context (th, [&] (auto *context)
>      {
> -      return get_context_reg_ptr (context, r);
> +      return get_context_reg_ptr (context, r, tdep);
>      });
> 
>    gdb_assert (!gdbarch_read_pc_p (gdbarch));
> @@ -333,7 +361,7 @@ x86_windows_nat_target::store_one_register (const
> struct regcache *regcache,
>      = x86_windows_process.with_context (th, [&] (auto *context)
>      {
>        gdb_assert (context->ContextFlags != 0);
> -      return get_context_reg_ptr (context, r);
> +      return get_context_reg_ptr (context, r, tdep);
>      });
> 
>    /* GDB treats some registers as 32-bit, where they are in fact only
> @@ -368,6 +396,23 @@ x86_windows_nat_target::is_sw_breakpoint (const
> EXCEPTION_RECORD *er) const
>  	  || er->ExceptionCode == STATUS_WX86_BREAKPOINT);
>  }
> 

Add

/* See target.h.  */

> +const struct target_desc *
> +x86_windows_nat_target::read_description ()
> +{
> +  if (inferior_ptid == null_ptid)
> +    return this->beneath ()->read_description ();
> +
> +  if (xstate_features == 0)
> +    return nullptr;
> +
> +#ifdef __x86_64__
> +  if (!x86_windows_process.wow64_process)
> +    return amd64_target_description (xstate_features, false);
> +  else
> +#endif
> +    return i386_target_description (xstate_features, false);
> +}
> +
>  /* Hardware watchpoint support, adapted from go32-nat.c code.  */
> 
>  /* Pass the address ADDR to the inferior in the I'th debug register.
> diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
> index b77f6adc6ed..1a45b15e0cf 100644
> --- a/gdbserver/win32-i386-low.cc
> +++ b/gdbserver/win32-i386-low.cc
> @@ -253,6 +253,11 @@ i386_get_thread_context (windows_thread_info
> *th)
>  			       | WindowsContext<decltype(context)>::floating
>  			       | WindowsContext<decltype(context)>::debug
>  			       | extended_registers);
> +      if (xstate_features != 0)
> +	{
> +	  context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> +	  set_xstate_features_mask (context, xstate_features);
> +	}
> 
>        BOOL ret = get_thread_context (th->h, context);
>        if (!ret)
> @@ -267,6 +272,8 @@ i386_get_thread_context (windows_thread_info *th)
> 
>  	  error (_("GetThreadContext failure %ld\n"), (long) e);
>  	}
> +
> +      th->zero_xstate_features ();
>      });
>  }
> 
> @@ -292,6 +299,17 @@ i386_prepare_to_resume (windows_thread_info
> *th)
> 
>        th->debug_registers_changed = false;
>      }
> +
> +  windows_process.with_context (th, [&] (auto *context)
> +    {
> +      DWORD debug_registers = WindowsContext<decltype(context)>::debug;
> +      if (xstate_features != 0
> +	  && (context->ContextFlags & ~debug_registers) != 0)
> +	{
> +	  context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> +	  set_xstate_features_mask (context, xstate_features);
> +	}
> +    });
>  }
> 
>  static void
> @@ -477,26 +495,40 @@ is_segment_register (int r)
> 
>  template<typename Context>
>  static char *
> -get_context_reg_ptr (Context *context, int r)
> +get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)
>  {
>    const int *mappings;
>    int mappings_count;
> +  bool amd64;
>  #ifdef __x86_64__
>    if (!windows_process.wow64_process)
>      {
>        mappings = amd64_mappings;
>        mappings_count = sizeof (amd64_mappings) / sizeof
> (amd64_mappings[0]);
> +      amd64 = true;
>      }
>    else
>  #endif
>      {
>        mappings = i386_mappings;
>        mappings_count = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
> +      amd64 = false;
>      }
> 
> +  int ymm0h_regnum;
> +  const int num_xmm_registers = amd64 ? 16 : 8;
> +
>    char *context_offset;
>    if (r < mappings_count)
>      context_offset = (char *) context + mappings[r];
> +  else if ((xstate_features & X86_XSTATE_AVX) != 0
> +	   && r >= (ymm0h_regnum = find_regno (tdesc, "ymm0h"))
> +	   && r < ymm0h_regnum + num_xmm_registers)
> +    {
> +      context_offset = (char *) locate_xstate_feature
> +	(context, X86_XSTATE_AVX_ID, nullptr);

We don't check "context_offset" for nulltpr before adding the offsets. We're
checking for nullptr and size explicitly in "zero_xstate_features".  So, I was
wondering if we should add checks here, too.  IIUC, it should not be possible
to have "locate_xstate_feature () == nullptr" at this point.  Maybe add an
assert for consistency?

> +      context_offset += 16 * (r - ymm0h_regnum);
> +    }
>    else
>      gdb_assert_not_reached ("invalid register number %d", r);
> 
> @@ -510,7 +542,7 @@ i386_fetch_inferior_register (struct regcache
> *regcache,
>  {
>    char *context_offset = windows_process.with_context (th, [&] (auto
> *context)
>      {
> -      return get_context_reg_ptr (context, r);
> +      return get_context_reg_ptr (context, r, regcache->tdesc);
>      });
> 
>    /* GDB treats some registers as 32-bit, where they are in fact only
> @@ -538,7 +570,7 @@ i386_store_inferior_register (struct regcache
> *regcache,
>  {
>    char *context_offset = windows_process.with_context (th, [&] (auto
> *context)
>      {
> -      return get_context_reg_ptr (context, r);
> +      return get_context_reg_ptr (context, r, regcache->tdesc);
>      });
> 
>    /* GDB treats some registers as 32-bit, where they are in fact only
> @@ -571,14 +603,17 @@ i386_arch_setup (void)
>  {
>   target_desc_up tdesc;
> 
> +  DWORD64 xcr0 = xstate_features;
> +  if (xcr0 == 0)
> +    xcr0 = X86_XSTATE_SSE_MASK;
> +
>  #ifdef __x86_64__
> -  tdesc = amd64_create_target_description (X86_XSTATE_SSE_MASK, false,
> -					   false, false);
> +  tdesc = amd64_create_target_description (xcr0, false, false, false);
>    init_target_desc (tdesc.get (), amd64_expedite_regs, WINDOWS_OSABI);
>    win32_tdesc = std::move (tdesc);
>  #endif
> 
> -  tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false,
> false);
> +  tdesc = i386_create_target_description (xcr0, false, false);
>    init_target_desc (tdesc.get (), i386_expedite_regs, WINDOWS_OSABI);
>  #ifdef __x86_64__
>    wow64_win32_tdesc = std::move (tdesc);
> diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
> index 1103a802db7..3e80405f651 100644
> --- a/gdbserver/win32-low.cc
> +++ b/gdbserver/win32-low.cc
> @@ -33,6 +33,7 @@
>  #include <process.h>
>  #include "gdbsupport/gdb_tilde_expand.h"
>  #include "gdbsupport/common-inferior.h"
> +#include "tdesc.h"
> 
>  using namespace windows_nat;
> 
> @@ -427,8 +428,9 @@ child_fetch_inferior_registers (struct regcache
> *regcache, int r)
>    int regno;
>    windows_thread_info *th = windows_process.find_thread (current_thread-
> >id);
>    win32_require_context (th);
> -  if (r == -1 || r > NUM_REGS)
> -    child_fetch_inferior_registers (regcache, NUM_REGS);

With r != -1 and r > regcache->tdesc->reg_defs.size (), this may fall through into
"get_context_reg_ptr" and eventually into the gdb_assert_not_reached_part.

Maybe add another check, e.g.,

    int num_regs = regcache->tdesc->reg_defs.size ();
    if (r == -1 || r > num_regs)
      r = num_regs;

Same for child_store_inferior_registers.

> +  if (r == -1)
> +    child_fetch_inferior_registers (regcache,
> +				    regcache->tdesc->reg_defs.size ());
>    else
>      for (regno = 0; regno < r; regno++)
>        (*the_low_target.fetch_inferior_register) (regcache, th, regno);
> @@ -442,8 +444,9 @@ child_store_inferior_registers (struct regcache
> *regcache, int r)
>    int regno;
>    windows_thread_info *th = windows_process.find_thread (current_thread-
> >id);
>    win32_require_context (th);
> -  if (r == -1 || r == 0 || r > NUM_REGS)
> -    child_store_inferior_registers (regcache, NUM_REGS);
> +  if (r == -1 || r == 0)
> +    child_store_inferior_registers (regcache,
> +				    regcache->tdesc->reg_defs.size ());
>    else
>      for (regno = 0; regno < r; regno++)
>        (*the_low_target.store_inferior_register) (regcache, th, regno);
> @@ -1347,7 +1350,9 @@ void
>  initialize_low (void)
>  {
>    set_target_ops (&the_win32_target);
> -  the_low_target.arch_setup ();
> 
>    initialize_loadable ();
> +  /* Has to be done after initialize_loadable, because it uses the xstate
> +     functions if available.  */
> +  the_low_target.arch_setup ();
>  }
> --
> 2.55.0

________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* Re: [PATCH v4 7/9] Windows gdb: Implement AVX register support
  2026-10-05 14:09     ` Rohr, Stephan
@ 2026-10-09 14:30       ` Hannes Domani
  2026-10-14 13:04         ` Joos, Christina
  0 siblings, 1 reply; 18+ messages in thread
From: Hannes Domani @ 2026-10-09 14:30 UTC (permalink / raw)
  To: gdb-patches, Rohr, Stephan; +Cc: Joos, Christina

 Am Montag, 5. Oktober 2026 um 16:09:22 MESZ hat Rohr, Stephan <stephan.rohr@intel.com> Folgendes geschrieben:

> Hi Hannes,
> 
> some minor findings below.
> 
> With those fixed.
> 
> Reviewed-By: Rohr, Stephan <stephan.rohr@intel.com>
> 
> Thanks
> Stephan
> 
> > -----Original Message-----
> > From: Hannes Domani <ssbssa@yahoo.de>
> > Sent: Wednesday, 30 September 2026 17:12
> > To: gdb-patches@sourceware.org
> > Subject: [PATCH v4 7/9] Windows gdb: Implement AVX register support
> >
> > This adds support for the Intel AVX registers on Windows.
> > It enables accessing registers $ymm0 - $ymm15 where they are available.
> >
> > After this patch gdb.arch/i386-avx.exp passes on windows.
> > ---
> > v3:
> > - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
> > v4:
> > - fixed $ymm15 in NEWS
> > - Add common function windows_thread_info::zero_xstate_features,
> > and fix maximum supported feature in for-loop
> > - Add check for enabled xstate_features in get_context_reg_ptr of
> > x86-windows-nat.c
> > - Move amd64 variable in get_context_reg_ptr of win32-i386-low.cc
> > - Changed all NULL to nullptr
> > - Don't remove 'r == 0' from child_store_inferior_registers
> > ---
> > gdb/NEWS | 3 +++
> > gdb/nat/windows-nat.c | 36 +++++++++++++++++++++++++-
> > gdb/nat/windows-nat.h | 6 +++++
> > gdb/x86-windows-nat.c | 51
> > ++++++++++++++++++++++++++++++++++---
> > gdbserver/win32-i386-low.cc | 47 +++++++++++++++++++++++++++++-----
> > gdbserver/win32-low.cc | 15 +++++++----
> > 6 files changed, 143 insertions(+), 15 deletions(-)
> >
> > diff --git a/gdb/NEWS b/gdb/NEWS
> > index 5d0c4745653..da4bc811c3a 100644
> > --- a/gdb/NEWS
> > +++ b/gdb/NEWS
> > @@ -194,6 +194,9 @@ info locals
> > intent to remove it in a future release.
> > The s390 64-bit target (s390x-*) remains supported.
> >
> > +* Support for Intel AVX registers on Windows.
> > + Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
> > +
> > * Configure changes
> >
> > ** --with-babeltrace has been removed. The babeltrace library was
> > diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
> > index 58be5368a79..cd3c827a5d5 100644
> > --- a/gdb/nat/windows-nat.c
> > +++ b/gdb/nat/windows-nat.c
> > @@ -271,6 +271,40 @@ windows_thread_info::xfer_siginfo (gdb_byte
> > *readbuf,
> > return true;
> > }
> >
> > +#if defined __i386__ || defined __x86_64__
> > +/* See nat/windows-nat.h. */
> > +
> > +void
> > +windows_thread_info::zero_xstate_features ()
> > +{
> > + if (xstate_features == 0)
> > + return;
> > +
> > + proc->with_context (this, [] (auto *context)
> > + {
> > + DWORD64 features = 0;
> > + if (!get_xstate_features_mask (context, &features))
> > + return;
> > +
> > + DWORD64 zeroed_features = xstate_features & ~features;
> > + if (zeroed_features == 0)
> > + return;
> > +
> > + for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
> 
> Start == End.

That's intentional, it changes with the next patch anyways.


> > + {
> > + DWORD64 flag = 1ULL << f;
> > + if ((zeroed_features & flag) != 0)
> > + {
> > + DWORD size = 0;
> > + void *loc = locate_xstate_feature (context, f, &size);
> > + if (loc != nullptr && size > 0)
> > + memset (loc, 0, size);
> > + }
> > + }
> > + });
> > +}
> > +#endif
> > +
> > /* Try to determine the executable filename.
> >
> > EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
> > @@ -1339,7 +1373,7 @@ initialize_loadable ()
> > {
> > /* Available XState features masked with implemented features. */
> > xstate_features = (GetEnabledXStateFeatures ()
> > - & X86_XSTATE_SSE_MASK);
> > + & X86_XSTATE_AVX_MASK);
> > /* The extended XState functions are only needed if the available
> > features exceed SSE. */
> > if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
> > diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
> > index a7d4af84e13..4cd75cb6a0e 100644
> > --- a/gdb/nat/windows-nat.h
> > +++ b/gdb/nat/windows-nat.h
> > @@ -90,6 +90,12 @@ struct windows_thread_info
> > ULONGEST offset, ULONGEST len,
> > ULONGEST *xfered_len);
> >
> > +#if defined __i386__ || defined __x86_64__
> > + /* Zero all XState feature areas that were not provided by
> > + GetThreadContext. */
> > + void zero_xstate_features ();
> > +#endif
> > +
> > /* The process this thread belongs to. */
> > windows_process_info *const proc;
> >
> > diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
> > index 3af5ef4dae0..1e44a45171c 100644
> > --- a/gdb/x86-windows-nat.c
> > +++ b/gdb/x86-windows-nat.c
> > @@ -27,6 +27,9 @@
> >
> > #include "i386-tdep.h"
> > #include "i387-tdep.h"
> > +#ifdef __x86_64__
> > +#include "amd64-tdep.h"
> > +#endif
> >
> > using namespace windows_nat;
> >
> > @@ -70,6 +73,8 @@ struct x86_windows_nat_target final : public
> > x86_nat_target<windows_nat_target>
> > windows_thread_info *th, int r) override;
> >
> > bool is_sw_breakpoint (const EXCEPTION_RECORD *er) const override;
> > +
> > + const struct target_desc *read_description () override;
> > };
> >
> > /* The current process. */
> > @@ -109,7 +114,14 @@ x86_windows_per_inferior::fill_thread_context
> > (windows_thread_info *th)
> > if (context->ContextFlags == 0)
> > {
> > context->ContextFlags = WindowsContext<decltype(context)>::all;
> > + if (xstate_features != 0)
> > + {
> > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > + set_xstate_features_mask (context, xstate_features);
> > + }
> > CHECK (get_thread_context (th->h, context));
> > +
> > + th->zero_xstate_features ();
> > }
> > });
> > }
> > @@ -198,6 +210,14 @@
> > x86_windows_nat_target::thread_context_continue (windows_thread_info
> > *th,
> > if (GetExitCodeThread (th->h, &ec)
> > && ec == STILL_ACTIVE)
> > {
> > + DWORD debug_registers =
> > WindowsContext<decltype(context)>::debug;
> > + if (xstate_features != 0
> > + && (context->ContextFlags & ~debug_registers) != 0)
> > + {
> > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > + set_xstate_features_mask (context, xstate_features);
> > + }
> > +
> > BOOL status = set_thread_context (th->h, context);
> >
> > if (!killed)
> > @@ -227,7 +247,7 @@ x86_windows_nat_target::thread_context_step
> > (windows_thread_info *th,
> >
> > template<typename Context>
> > static char *
> > -get_context_reg_ptr (Context *context, int r)
> > +get_context_reg_ptr (Context *context, int r, i386_gdbarch_tdep *tdep)
> > {
> > const int *mappings;
> > int mappings_count;
> > @@ -247,6 +267,14 @@ get_context_reg_ptr (Context *context, int r)
> > char *context_offset;
> > if (r < mappings_count)
> > context_offset = (char *) context + mappings[r];
> > + else if ((xstate_features & X86_XSTATE_AVX) != 0
> > + && I387_YMM0H_REGNUM (tdep) > 0 && r >=
> > I387_YMM0H_REGNUM (tdep)
> > + && r < I387_YMMENDH_REGNUM (tdep))
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_AVX_ID, nullptr);
> > + context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
> > + }
> > else
> > gdb_assert_not_reached ("invalid register number %d", r);
> >
> > @@ -267,7 +295,7 @@ x86_windows_nat_target::fetch_one_register (struct
> > regcache *regcache,
> > char *context_offset
> > = x86_windows_process.with_context (th, [&] (auto *context)
> > {
> > - return get_context_reg_ptr (context, r);
> > + return get_context_reg_ptr (context, r, tdep);
> > });
> >
> > gdb_assert (!gdbarch_read_pc_p (gdbarch));
> > @@ -333,7 +361,7 @@ x86_windows_nat_target::store_one_register (const
> > struct regcache *regcache,
> > = x86_windows_process.with_context (th, [&] (auto *context)
> > {
> > gdb_assert (context->ContextFlags != 0);
> > - return get_context_reg_ptr (context, r);
> > + return get_context_reg_ptr (context, r, tdep);
> > });
> >
> > /* GDB treats some registers as 32-bit, where they are in fact only
> > @@ -368,6 +396,23 @@ x86_windows_nat_target::is_sw_breakpoint (const
> > EXCEPTION_RECORD *er) const
> > || er->ExceptionCode == STATUS_WX86_BREAKPOINT);
> > }
> >
> 
> Add
> 
> /* See target.h. */

Ok.


> > +const struct target_desc *
> > +x86_windows_nat_target::read_description ()
> > +{
> > + if (inferior_ptid == null_ptid)
> > + return this->beneath ()->read_description ();
> > +
> > + if (xstate_features == 0)
> > + return nullptr;
> > +
> > +#ifdef __x86_64__
> > + if (!x86_windows_process.wow64_process)
> > + return amd64_target_description (xstate_features, false);
> > + else
> > +#endif
> > + return i386_target_description (xstate_features, false);
> > +}
> > +
> > /* Hardware watchpoint support, adapted from go32-nat.c code. */
> >
> > /* Pass the address ADDR to the inferior in the I'th debug register.
> > diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
> > index b77f6adc6ed..1a45b15e0cf 100644
> > --- a/gdbserver/win32-i386-low.cc
> > +++ b/gdbserver/win32-i386-low.cc
> > @@ -253,6 +253,11 @@ i386_get_thread_context (windows_thread_info
> > *th)
> > | WindowsContext<decltype(context)>::floating
> > | WindowsContext<decltype(context)>::debug
> > | extended_registers);
> > + if (xstate_features != 0)
> > + {
> > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > + set_xstate_features_mask (context, xstate_features);
> > + }
> >
> > BOOL ret = get_thread_context (th->h, context);
> > if (!ret)
> > @@ -267,6 +272,8 @@ i386_get_thread_context (windows_thread_info *th)
> >
> > error (_("GetThreadContext failure %ld\n"), (long) e);
> > }
> > +
> > + th->zero_xstate_features ();
> > });
> > }
> >
> > @@ -292,6 +299,17 @@ i386_prepare_to_resume (windows_thread_info
> > *th)
> >
> > th->debug_registers_changed = false;
> > }
> > +
> > + windows_process.with_context (th, [&] (auto *context)
> > + {
> > + DWORD debug_registers = WindowsContext<decltype(context)>::debug;
> > + if (xstate_features != 0
> > + && (context->ContextFlags & ~debug_registers) != 0)
> > + {
> > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > + set_xstate_features_mask (context, xstate_features);
> > + }
> > + });
> > }
> >
> > static void
> > @@ -477,26 +495,40 @@ is_segment_register (int r)
> >
> > template<typename Context>
> > static char *
> > -get_context_reg_ptr (Context *context, int r)
> > +get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)
> > {
> > const int *mappings;
> > int mappings_count;
> > + bool amd64;
> > #ifdef __x86_64__
> > if (!windows_process.wow64_process)
> > {
> > mappings = amd64_mappings;
> > mappings_count = sizeof (amd64_mappings) / sizeof
> > (amd64_mappings[0]);
> > + amd64 = true;
> > }
> > else
> > #endif
> > {
> > mappings = i386_mappings;
> > mappings_count = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
> > + amd64 = false;
> > }
> >
> > + int ymm0h_regnum;
> > + const int num_xmm_registers = amd64 ? 16 : 8;
> > +
> > char *context_offset;
> > if (r < mappings_count)
> > context_offset = (char *) context + mappings[r];
> > + else if ((xstate_features & X86_XSTATE_AVX) != 0
> > + && r >= (ymm0h_regnum = find_regno (tdesc, "ymm0h"))
> > + && r < ymm0h_regnum + num_xmm_registers)
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_AVX_ID, nullptr);
> 
> We don't check "context_offset" for nulltpr before adding the offsets. We're
> checking for nullptr and size explicitly in "zero_xstate_features". So, I was
> wondering if we should add checks here, too. IIUC, it should not be possible
> to have "locate_xstate_feature () == nullptr" at this point. Maybe add an
> assert for consistency?

Same for x86-windows-nat.c?


> > + context_offset += 16 * (r - ymm0h_regnum);
> > + }
> > else
> > gdb_assert_not_reached ("invalid register number %d", r);
> >
> > @@ -510,7 +542,7 @@ i386_fetch_inferior_register (struct regcache
> > *regcache,
> > {
> > char *context_offset = windows_process.with_context (th, [&] (auto
> > *context)
> > {
> > - return get_context_reg_ptr (context, r);
> > + return get_context_reg_ptr (context, r, regcache->tdesc);
> > });
> >
> > /* GDB treats some registers as 32-bit, where they are in fact only
> > @@ -538,7 +570,7 @@ i386_store_inferior_register (struct regcache
> > *regcache,
> > {
> > char *context_offset = windows_process.with_context (th, [&] (auto
> > *context)
> > {
> > - return get_context_reg_ptr (context, r);
> > + return get_context_reg_ptr (context, r, regcache->tdesc);
> > });
> >
> > /* GDB treats some registers as 32-bit, where they are in fact only
> > @@ -571,14 +603,17 @@ i386_arch_setup (void)
> > {
> > target_desc_up tdesc;
> >
> > + DWORD64 xcr0 = xstate_features;
> > + if (xcr0 == 0)
> > + xcr0 = X86_XSTATE_SSE_MASK;
> > +
> > #ifdef __x86_64__
> > - tdesc = amd64_create_target_description (X86_XSTATE_SSE_MASK, false,
> > - false, false);
> > + tdesc = amd64_create_target_description (xcr0, false, false, false);
> > init_target_desc (tdesc.get (), amd64_expedite_regs, WINDOWS_OSABI);
> > win32_tdesc = std::move (tdesc);
> > #endif
> >
> > - tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false,
> > false);
> > + tdesc = i386_create_target_description (xcr0, false, false);
> > init_target_desc (tdesc.get (), i386_expedite_regs, WINDOWS_OSABI);
> > #ifdef __x86_64__
> > wow64_win32_tdesc = std::move (tdesc);
> > diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
> > index 1103a802db7..3e80405f651 100644
> > --- a/gdbserver/win32-low.cc
> > +++ b/gdbserver/win32-low.cc
> > @@ -33,6 +33,7 @@
> > #include <process.h>
> > #include "gdbsupport/gdb_tilde_expand.h"
> > #include "gdbsupport/common-inferior.h"
> > +#include "tdesc.h"
> >
> > using namespace windows_nat;
> >
> > @@ -427,8 +428,9 @@ child_fetch_inferior_registers (struct regcache
> > *regcache, int r)
> > int regno;
> > windows_thread_info *th = windows_process.find_thread (current_thread-
> > >id);
> > win32_require_context (th);
> > - if (r == -1 || r > NUM_REGS)
> > - child_fetch_inferior_registers (regcache, NUM_REGS);
> 
> With r != -1 and r > regcache->tdesc->reg_defs.size (), this may fall through into
> "get_context_reg_ptr" and eventually into the gdb_assert_not_reached_part.
> 
> Maybe add another check, e.g.,
> 
> int num_regs = regcache->tdesc->reg_defs.size ();
> if (r == -1 || r > num_regs)
> r = num_regs;
> 
> Same for child_store_inferior_registers.

Adding this is fine with me, but I just wonder why r > reg_defs.size()
shouldn't get to gdb_assert_not_reached_part.


> > + if (r == -1)
> > + child_fetch_inferior_registers (regcache,
> > + regcache->tdesc->reg_defs.size ());
> > else
> > for (regno = 0; regno < r; regno++)
> > (*the_low_target.fetch_inferior_register) (regcache, th, regno);
> > @@ -442,8 +444,9 @@ child_store_inferior_registers (struct regcache
> > *regcache, int r)
> > int regno;
> > windows_thread_info *th = windows_process.find_thread (current_thread-
> > >id);
> > win32_require_context (th);
> > - if (r == -1 || r == 0 || r > NUM_REGS)
> > - child_store_inferior_registers (regcache, NUM_REGS);
> > + if (r == -1 || r == 0)
> > + child_store_inferior_registers (regcache,
> > + regcache->tdesc->reg_defs.size ());
> > else
> > for (regno = 0; regno < r; regno++)
> > (*the_low_target.store_inferior_register) (regcache, th, regno);
> > @@ -1347,7 +1350,9 @@ void
> > initialize_low (void)
> > {
> > set_target_ops (&the_win32_target);
> > - the_low_target.arch_setup ();
> >
> > initialize_loadable ();
> > + /* Has to be done after initialize_loadable, because it uses the xstate
> > + functions if available. */
> > + the_low_target.arch_setup ();
> > }
> > --
> > 2.55.0


Hannes

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

* Re: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
  2026-10-05 14:08     ` Rohr, Stephan
@ 2026-10-09 14:36       ` Hannes Domani
  2026-10-12  7:59         ` Joos, Christina
  2026-10-14 13:06         ` Joos, Christina
  0 siblings, 2 replies; 18+ messages in thread
From: Hannes Domani @ 2026-10-09 14:36 UTC (permalink / raw)
  To: gdb-patches, Rohr, Stephan; +Cc: Joos, Christina

 Am Montag, 5. Oktober 2026 um 16:09:19 MESZ hat Rohr, Stephan <stephan.rohr@intel.com> Folgendes geschrieben:

> Hi Hanns,
> 
> also here, some minor findings below.
> 
> Thanks
> Stephan
> 
> > -----Original Message-----
> > From: Hannes Domani <ssbssa@yahoo.de>
> > Sent: Wednesday, 30 September 2026 17:12
> > To: gdb-patches@sourceware.org
> > Subject: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
> >
> > Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for Linux,
> 
> Maybe name the commit title instead of the hash. Not sure what is best
> practice for this.

This part was suggested to me in another review, so maybe I should just
add both commit hash and title.


> > this patch adds support for the Intel AVX-512 registers for 32 and 64-bit
> > mode on Windows.
> > It enables accessing registers $ymm0 - $ymm31, $zmm0 - $zmm31, and
> > $k0 - $k7 where they are available.
> >
> 
> Wouldn't we want to mention "It enables accessing registers
> $ymm16 - $ymm31 [..]" instead?

Ok.


> > After this patch gdb.arch/i386-avx512.exp passes on windows.
> > ---
> > v3:
> > - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
> > v4:
> > - Add reference to equivalent Linux commit in commit message
> > - Add check for enabled xstate_features in get_context_reg_ptr of
> > x86-windows-nat.c
> > - Changed all NULL to nullptr
> > ---
> > gdb/NEWS | 4 +++-
> > gdb/nat/windows-nat.c | 4 ++--
> > gdb/x86-windows-nat.c | 40 +++++++++++++++++++++++++++++++
> > gdbserver/win32-i386-low.cc | 48
> > ++++++++++++++++++++++++++++++++++++-
> > 4 files changed, 92 insertions(+), 4 deletions(-)
> >
> > diff --git a/gdb/NEWS b/gdb/NEWS
> > index da4bc811c3a..704e6a7c8ba 100644
> > --- a/gdb/NEWS
> > +++ b/gdb/NEWS
> > @@ -195,7 +195,9 @@ info locals
> > The s390 64-bit target (s390x-*) remains supported.
> >
> > * Support for Intel AVX registers on Windows.
> > - Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
> > + Support displaying and modifying Intel AVX registers $ymm0 - $ymm31.
> 
> AVX is limited to $ymm0 - $ymm15. Maybe add another bullet
> "Support for Intel AVX-512 registers on Windows." and list what's introduced
> in this patch.

Ok.


> > + Support displaying and modifying Intel AVX-512 registers $zmm0 - $zmm31
> > + and $k0 - $k7.
> >
> > * Configure changes
> >
> > diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
> > index cd3c827a5d5..3940465d06b 100644
> > --- a/gdb/nat/windows-nat.c
> > +++ b/gdb/nat/windows-nat.c
> > @@ -290,7 +290,7 @@ windows_thread_info::zero_xstate_features ()
> > if (zeroed_features == 0)
> > return;
> >
> > - for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
> > + for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_ZMM_ID; f++)
> > {
> > DWORD64 flag = 1ULL << f;
> > if ((zeroed_features & flag) != 0)
> > @@ -1373,7 +1373,7 @@ initialize_loadable ()
> > {
> > /* Available XState features masked with implemented features. */
> > xstate_features = (GetEnabledXStateFeatures ()
> > - & X86_XSTATE_AVX_MASK);
> > + & X86_XSTATE_AVX_AVX512_MASK);
> 
> I think it makes sense to add a check that bits X86_XSTATE_K, X86_XSTATE_ZMM_H
> and X86_XSTATE_ZMM are all set. x86-xstate.h explicitly mentions
> "AVX 512 adds three feature bits. All three must be enabled.". I know this is a
> theoretical example but it doesn't hurt, e.g.,
> 
> if ((xstate_features & X86_XSTATE_AVX512) != X86_XSTATE_AVX512)
> xstate_features &= ~X86_XSTATE_AVX512;

I don't really get the why, but ok.


> > /* The extended XState functions are only needed if the available
> > features exceed SSE. */
> > if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
> > diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
> > index 1e44a45171c..afc71b4ef61 100644
> > --- a/gdb/x86-windows-nat.c
> > +++ b/gdb/x86-windows-nat.c
> > @@ -275,6 +275,46 @@ get_context_reg_ptr (Context *context, int r,
> > i386_gdbarch_tdep *tdep)
> > (context, X86_XSTATE_AVX_ID, nullptr);
> > context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
> > }
> > + else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> > + && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> > I387_ZMM0H_REGNUM (tdep)
> > + && r < I387_ZMM16H_REGNUM (tdep) && r <
> > I387_ZMMENDH_REGNUM (tdep))
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_H_ID, nullptr);
> > + context_offset += 32 * (r - I387_ZMM0H_REGNUM (tdep));
> > + }
> > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > + && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> > I387_ZMM16H_REGNUM (tdep)
> > + && r < I387_ZMMENDH_REGNUM (tdep))
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > + context_offset += 32 + 64 * (r - I387_ZMM16H_REGNUM (tdep));
> > + }
> > + else if ((xstate_features & X86_XSTATE_K) != 0
> > + && I387_K0_REGNUM (tdep) > 0 && r >= I387_K0_REGNUM (tdep)
> > + && r < I387_KEND_REGNUM (tdep))
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_K_ID, nullptr);
> > + context_offset += 8 * (r - I387_K0_REGNUM (tdep));
> > + }
> > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > + && I387_YMM16H_REGNUM (tdep) > 0 && r >=
> > I387_YMM16H_REGNUM (tdep)
> > + && r < I387_YMMH_AVX512_END_REGNUM (tdep))
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > + context_offset += 16 + 64 * (r - I387_YMM16H_REGNUM (tdep));
> > + }
> > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > + && I387_XMM16_REGNUM (tdep) > 0 && r >=
> > I387_XMM16_REGNUM (tdep)
> > + && r < I387_XMM_AVX512_END_REGNUM (tdep))
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > + context_offset += 64 * (r - I387_XMM16_REGNUM (tdep));
> > + }
> > else
> > gdb_assert_not_reached ("invalid register number %d", r);
> >
> > diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
> > index 1a45b15e0cf..8c62787a31b 100644
> > --- a/gdbserver/win32-i386-low.cc
> > +++ b/gdbserver/win32-i386-low.cc
> > @@ -515,8 +515,11 @@ get_context_reg_ptr (Context *context, int r, const
> > target_desc *tdesc)
> > amd64 = false;
> > }
> >
> > - int ymm0h_regnum;
> > + int ymm0h_regnum, zmm0h_regnum, k0_regnum;
> > + int xmm16_regnum, ymm16h_regnum, zmm16h_regnum;
> > const int num_xmm_registers = amd64 ? 16 : 8;
> > + const int num_zmm_high_registers = amd64 ? 16 : 0;
> > + const int num_avx512_k_registers = 8;
> >
> > char *context_offset;
> > if (r < mappings_count)
> > @@ -529,6 +532,49 @@ get_context_reg_ptr (Context *context, int r, const
> > target_desc *tdesc)
> > (context, X86_XSTATE_AVX_ID, nullptr);
> > context_offset += 16 * (r - ymm0h_regnum);
> > }
> > + else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> > + && r >= (zmm0h_regnum = find_regno (tdesc, "zmm0h"))
> > + && r < zmm0h_regnum + num_xmm_registers)
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_H_ID, nullptr);
> > + context_offset += 32 * (r - zmm0h_regnum);
> > + }
> > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > + && num_zmm_high_registers != 0
> > + && r >= (zmm16h_regnum = find_regno (tdesc, "zmm16h"))
> > + && r < zmm16h_regnum + num_zmm_high_registers)
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > + context_offset += 32 + 64 * (r - zmm16h_regnum);
> > + }
> > + else if ((xstate_features & X86_XSTATE_K) != 0
> > + && r >= (k0_regnum = find_regno (tdesc, "k0"))
> > + && r < k0_regnum + num_avx512_k_registers)
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_K_ID, nullptr);
> > + context_offset += 8 * (r - k0_regnum);
> > + }
> > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > + && num_zmm_high_registers != 0
> > + && r >= (ymm16h_regnum = find_regno (tdesc, "ymm16h"))
> > + && r < ymm16h_regnum + num_zmm_high_registers)
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > + context_offset += 16 + 64 * (r - ymm16h_regnum);
> > + }
> > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > + && num_zmm_high_registers != 0
> > + && r >= (xmm16_regnum = find_regno (tdesc, "xmm16"))
> > + && r < xmm16_regnum + num_zmm_high_registers)
> > + {
> > + context_offset = (char *) locate_xstate_feature
> > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > + context_offset += 64 * (r - xmm16_regnum);
> > + }
> > else
> > gdb_assert_not_reached ("invalid register number %d", r);
> >
> > --
> > 2.55.0


Hannes

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

* RE: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
  2026-10-09 14:36       ` Hannes Domani
@ 2026-10-12  7:59         ` Joos, Christina
  2026-10-12 18:33           ` Hannes Domani
  2026-10-14 13:06         ` Joos, Christina
  1 sibling, 1 reply; 18+ messages in thread
From: Joos, Christina @ 2026-10-12  7:59 UTC (permalink / raw)
  To: Hannes Domani, gdb-patches, Rohr, Stephan

Hi Hannes,

Thanks for continuing to work on this. 

> > > Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for
> > > Linux,
> >
> > Maybe name the commit title instead of the hash. Not sure what is best
> > practice for this.
> 
> This part was suggested to me in another review, so maybe I should just add
> both commit hash and title.

Showing the commit message is definitely a good idea.
My initial review wasn't specific on how exactly you should reference the commit, sorry for that.
I think this commit is a good example:

https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=6b369b641c0efeee51356f72d7b317a8906bb8f3

I just started looking at this again and have one question upfront:
You explained that you ran the dedicated tests for AVX/AVX-512 etc, but has this series also been regression-tested?

Thanks,
Christina


________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* Re: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
  2026-10-12  7:59         ` Joos, Christina
@ 2026-10-12 18:33           ` Hannes Domani
  2026-10-26 12:28             ` Joos, Christina
  0 siblings, 1 reply; 18+ messages in thread
From: Hannes Domani @ 2026-10-12 18:33 UTC (permalink / raw)
  To: gdb-patches, Rohr, Stephan, Joos, Christina

 Am Montag, 12. Oktober 2026 um 09:59:47 MESZ hat Joos, Christina <christina.joos@intel.com> Folgendes geschrieben:

> Hi Hannes,
> 
> Thanks for continuing to work on this.
> 
> > > > Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for
> > > > Linux,
> > >
> > > Maybe name the commit title instead of the hash. Not sure what is best
> > > practice for this.
> >
> > This part was suggested to me in another review, so maybe I should just add
> > both commit hash and title.
> 
> Showing the commit message is definitely a good idea.
> My initial review wasn't specific on how exactly you should reference the commit, sorry for that.
> I think this commit is a good example:
> 
> https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=6b369b641c0efeee51356f72d7b317a8906bb8f3
> 
> I just started looking at this again and have one question upfront:
> You explained that you ran the dedicated tests for AVX/AVX-512 etc, but has this series also been regression-tested?

Sadly, the testsuite is very unreliable on windows (even though it improved
a lot recently).

I now let it first run with current master as baseline:

# of expected passes 42520
# of unexpected failures 3334
# of unexpected successes 1
# of expected failures 25
# of known failures 45
# of untested testcases 133
# of unresolved testcases 574
# of unsupported tests 356
# of paths in test names 32
# of duplicate test names 60

Then one time with my AVX changes:

# of expected passes 41663
# of unexpected failures 3686
# of unexpected successes 1
# of expected failures 26
# of known failures 45
# of untested testcases 135
# of unresolved testcases 565
# of unsupported tests 355
# of paths in test names 31
# of duplicate test names 54

And again with my changes, so you see what I mean:

# of expected passes 44348
# of unexpected failures 2894
# of unexpected successes 1
# of expected failures 23
# of known failures 45
# of untested testcases 134
# of unresolved testcases 306
# of unsupported tests 359
# of paths in test names 30
# of duplicate test names 44

I think it's funny that even the duplicate test names are different each time.
This was only for gdb.arch/gdb.base/gdb.cp, most of the others wouldn't work anyways.

I can tell you that I first implemented this AVX stuff almost 2 years ago,
and had no problems using gdb related to it since then.


Hannes

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

* RE: [PATCH v4 7/9] Windows gdb: Implement AVX register support
  2026-10-09 14:30       ` Hannes Domani
@ 2026-10-14 13:04         ` Joos, Christina
  0 siblings, 0 replies; 18+ messages in thread
From: Joos, Christina @ 2026-10-14 13:04 UTC (permalink / raw)
  To: Hannes Domani, gdb-patches, Rohr, Stephan

Hi Hannes, 

Please find my feedback below.

The comments in this email are mostly minor nits, and some can be considered optional.

The one topic I'd like to discuss in a bit more detail is the per-register use of locate_xstate_feature.
I believe we already touched on this in the v3 review, but the discussion did not fully conclude, and I initially misunderstood your latest comment regarding the offsets.
I added my feedback now in the separate thread which also describes the background a bit:
https://sourceware.org/pipermail/gdb-patches/2026-October/231057.html

> -----Original Message-----
> From: Hannes Domani <ssbssa@yahoo.de>
> Sent: Freitag, 9. Oktober 2026 16:30
> To: gdb-patches@sourceware.org; Rohr, Stephan <stephan.rohr@intel.com>
> Cc: Joos, Christina <christina.joos@intel.com>
> Subject: Re: [PATCH v4 7/9] Windows gdb: Implement AVX register support
> 
>  Am Montag, 5. Oktober 2026 um 16:09:22 MESZ hat Rohr, Stephan
> <stephan.rohr@intel.com> Folgendes geschrieben:
> 
> > Hi Hannes,
> >
> > some minor findings below.
> >
> > With those fixed.
> >
> > Reviewed-By: Rohr, Stephan <stephan.rohr@intel.com>
> >
> > Thanks
> > Stephan
> >
> > > -----Original Message-----
> > > From: Hannes Domani <ssbssa@yahoo.de>
> > > Sent: Wednesday, 30 September 2026 17:12
> > > To: gdb-patches@sourceware.org
> > > Subject: [PATCH v4 7/9] Windows gdb: Implement AVX register support
> > >
> > > This adds support for the Intel AVX registers on Windows.
> > > It enables accessing registers $ymm0 - $ymm15 where they are available.
> > >
> > > After this patch gdb.arch/i386-avx.exp passes on windows.
> > > ---
> > > v3:
> > > - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
> > > v4:
> > > - fixed $ymm15 in NEWS
> > > - Add common function windows_thread_info::zero_xstate_features,
> > > and fix maximum supported feature in for-loop
> > > - Add check for enabled xstate_features in get_context_reg_ptr of
> > > x86-windows-nat.c
> > > - Move amd64 variable in get_context_reg_ptr of win32-i386-low.cc
> > > - Changed all NULL to nullptr
> > > - Don't remove 'r == 0' from child_store_inferior_registers
> > > ---
> > > gdb/NEWS | 3 +++
> > > gdb/nat/windows-nat.c | 36 +++++++++++++++++++++++++-
> > > gdb/nat/windows-nat.h | 6 +++++ gdb/x86-windows-nat.c | 51
> > > ++++++++++++++++++++++++++++++++++---
> > > gdbserver/win32-i386-low.cc | 47 +++++++++++++++++++++++++++++-----
> > > gdbserver/win32-low.cc | 15 +++++++----
> > > 6 files changed, 143 insertions(+), 15 deletions(-)
> > >
> > > diff --git a/gdb/NEWS b/gdb/NEWS
> > > index 5d0c4745653..da4bc811c3a 100644
> > > --- a/gdb/NEWS
> > > +++ b/gdb/NEWS
> > > @@ -194,6 +194,9 @@ info locals
> > > intent to remove it in a future release.
> > > The s390 64-bit target (s390x-*) remains supported.
> > >
> > > +* Support for Intel AVX registers on Windows.
> > > + Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
> > > +
> > > * Configure changes
> > >
> > > ** --with-babeltrace has been removed. The babeltrace library was
> > > diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c index
> > > 58be5368a79..cd3c827a5d5 100644
> > > --- a/gdb/nat/windows-nat.c
> > > +++ b/gdb/nat/windows-nat.c
> > > @@ -271,6 +271,40 @@ windows_thread_info::xfer_siginfo (gdb_byte
> > > *readbuf, return true; }
> > >
> > > +#if defined __i386__ || defined __x86_64__
> > > +/* See nat/windows-nat.h. */
> > > +
> > > +void
> > > +windows_thread_info::zero_xstate_features () {  if (xstate_features
> > > +== 0)  return;
> > > +
> > > + proc->with_context (this, [] (auto *context)
> > > + {
> > > + DWORD64 features = 0;
> > > + if (!get_xstate_features_mask (context, &features)) return;
> > > +
> > > + DWORD64 zeroed_features = xstate_features & ~features; if
> > > + (zeroed_features == 0) return;
> > > +
> > > + for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
> >
> > Start == End.
> 
> That's intentional, it changes with the next patch anyways.

I stumbled over this as well. However, I understand why you chose to keep it this way,
given that the next patch changes it, and I'm fine with that.

> 
> > > + {
> > > + DWORD64 flag = 1ULL << f;
> > > + if ((zeroed_features & flag) != 0)  {  DWORD size = 0;  void *loc
> > > += locate_xstate_feature (context, f, &size);  if (loc != nullptr &&
> > > +size > 0)  memset (loc, 0, size);  }  }  }); } #endif
> > > +
> > > /* Try to determine the executable filename.
> > >
> > > EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
> > > @@ -1339,7 +1373,7 @@ initialize_loadable () {
> > > /* Available XState features masked with implemented features. */
> > > xstate_features = (GetEnabledXStateFeatures ()
> > > - & X86_XSTATE_SSE_MASK);
> > > + & X86_XSTATE_AVX_MASK);
> > > /* The extended XState functions are only needed if the available
> > > features exceed SSE. */ if ((xstate_features & ~X86_XSTATE_SSE_MASK)
> > > == 0) diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
> > > index a7d4af84e13..4cd75cb6a0e 100644
> > > --- a/gdb/nat/windows-nat.h
> > > +++ b/gdb/nat/windows-nat.h
> > > @@ -90,6 +90,12 @@ struct windows_thread_info ULONGEST offset,
> > > ULONGEST len, ULONGEST *xfered_len);
> > >
> > > +#if defined __i386__ || defined __x86_64__
> > > + /* Zero all XState feature areas that were not provided by
> > > +GetThreadContext. */  void zero_xstate_features (); #endif
> > > +
> > > /* The process this thread belongs to. */ windows_process_info
> > > *const proc;
> > >
> > > diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c index
> > > 3af5ef4dae0..1e44a45171c 100644
> > > --- a/gdb/x86-windows-nat.c
> > > +++ b/gdb/x86-windows-nat.c
> > > @@ -27,6 +27,9 @@
> > >
> > > #include "i386-tdep.h"
> > > #include "i387-tdep.h"
> > > +#ifdef __x86_64__
> > > +#include "amd64-tdep.h"
> > > +#endif
> > >
> > > using namespace windows_nat;
> > >
> > > @@ -70,6 +73,8 @@ struct x86_windows_nat_target final : public
> > > x86_nat_target<windows_nat_target>
> > > windows_thread_info *th, int r) override;
> > >
> > > bool is_sw_breakpoint (const EXCEPTION_RECORD *er) const override;
> > > +
> > > + const struct target_desc *read_description () override;
> > > };
> > >
> > > /* The current process. */
> > > @@ -109,7 +114,14 @@ x86_windows_per_inferior::fill_thread_context
> > > (windows_thread_info *th)
> > > if (context->ContextFlags == 0)
> > > {
> > > context->ContextFlags = WindowsContext<decltype(context)>::all;
> > > + if (xstate_features != 0)
> > > + {
> > > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > > + set_xstate_features_mask (context, xstate_features); }
> > > CHECK (get_thread_context (th->h, context));
> > > +
> > > + th->zero_xstate_features ();
> > > }
> > > });
> > > }
> > > @@ -198,6 +210,14 @@
> > > x86_windows_nat_target::thread_context_continue (windows_thread_info
> > > *th,
> > > if (GetExitCodeThread (th->h, &ec)
> > > && ec == STILL_ACTIVE)
> > > {
> > > + DWORD debug_registers =
> > > WindowsContext<decltype(context)>::debug;
> > > + if (xstate_features != 0
> > > + && (context->ContextFlags & ~debug_registers) != 0)
> > > + {
> > > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > > + set_xstate_features_mask (context, xstate_features);
> > > + }
> > > +
> > > BOOL status = set_thread_context (th->h, context);
> > >
> > > if (!killed)
> > > @@ -227,7 +247,7 @@ x86_windows_nat_target::thread_context_step
> > > (windows_thread_info *th,
> > >
> > > template<typename Context>
> > > static char *
> > > -get_context_reg_ptr (Context *context, int r)
> > > +get_context_reg_ptr (Context *context, int r, i386_gdbarch_tdep *tdep)
> > > {

Nit: explain the new parameter in the function comment and in which cases this is required.

> > > const int *mappings;
> > > int mappings_count;
> > > @@ -247,6 +267,14 @@ get_context_reg_ptr (Context *context, int r)
> > > char *context_offset;
> > > if (r < mappings_count)
> > > context_offset = (char *) context + mappings[r];
> > > + else if ((xstate_features & X86_XSTATE_AVX) != 0
> > > + && I387_YMM0H_REGNUM (tdep) > 0 && r >=
> > > I387_YMM0H_REGNUM (tdep)
> > > + && r < I387_YMMENDH_REGNUM (tdep))
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_AVX_ID, nullptr);
> > > + context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
> > > + }
> > > else
> > > gdb_assert_not_reached ("invalid register number %d", r);
> > >
> > > @@ -267,7 +295,7 @@ x86_windows_nat_target::fetch_one_register (struct
> > > regcache *regcache,
> > > char *context_offset
> > > = x86_windows_process.with_context (th, [&] (auto *context)
> > > {
> > > - return get_context_reg_ptr (context, r);
> > > + return get_context_reg_ptr (context, r, tdep);
> > > });
> > >
> > > gdb_assert (!gdbarch_read_pc_p (gdbarch));
> > > @@ -333,7 +361,7 @@ x86_windows_nat_target::store_one_register (const
> > > struct regcache *regcache,
> > > = x86_windows_process.with_context (th, [&] (auto *context)
> > > {
> > > gdb_assert (context->ContextFlags != 0);
> > > - return get_context_reg_ptr (context, r);
> > > + return get_context_reg_ptr (context, r, tdep);
> > > });
> > >
> > > /* GDB treats some registers as 32-bit, where they are in fact only
> > > @@ -368,6 +396,23 @@ x86_windows_nat_target::is_sw_breakpoint (const
> > > EXCEPTION_RECORD *er) const
> > > || er->ExceptionCode == STATUS_WX86_BREAKPOINT);
> > > }
> > >
> >
> > Add
> >
> > /* See target.h. */
> 
> Ok.
> 
> 
> > > +const struct target_desc *
> > > +x86_windows_nat_target::read_description ()
> > > +{
> > > + if (inferior_ptid == null_ptid)
> > > + return this->beneath ()->read_description ();
> > > +
> > > + if (xstate_features == 0)
> > > + return nullptr;
> > > +
> > > +#ifdef __x86_64__
> > > + if (!x86_windows_process.wow64_process)
> > > + return amd64_target_description (xstate_features, false);
> > > + else
> > > +#endif
> > > + return i386_target_description (xstate_features, false);
> > > +}
> > > +
> > > /* Hardware watchpoint support, adapted from go32-nat.c code. */
> > >
> > > /* Pass the address ADDR to the inferior in the I'th debug register.
> > > diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
> > > index b77f6adc6ed..1a45b15e0cf 100644
> > > --- a/gdbserver/win32-i386-low.cc
> > > +++ b/gdbserver/win32-i386-low.cc
> > > @@ -253,6 +253,11 @@ i386_get_thread_context (windows_thread_info
> > > *th)
> > > | WindowsContext<decltype(context)>::floating
> > > | WindowsContext<decltype(context)>::debug
> > > | extended_registers);
> > > + if (xstate_features != 0)
> > > + {
> > > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > > + set_xstate_features_mask (context, xstate_features);
> > > + }
> > >
> > > BOOL ret = get_thread_context (th->h, context);
> > > if (!ret)
> > > @@ -267,6 +272,8 @@ i386_get_thread_context (windows_thread_info *th)
> > >
> > > error (_("GetThreadContext failure %ld\n"), (long) e);
> > > }
> > > +
> > > + th->zero_xstate_features ();
> > > });
> > > }
> > >
> > > @@ -292,6 +299,17 @@ i386_prepare_to_resume (windows_thread_info
> > > *th)
> > >
> > > th->debug_registers_changed = false;
> > > }
> > > +
> > > + windows_process.with_context (th, [&] (auto *context)
> > > + {
> > > + DWORD debug_registers = WindowsContext<decltype(context)>::debug;
> > > + if (xstate_features != 0
> > > + && (context->ContextFlags & ~debug_registers) != 0)
> > > + {
> > > + context->ContextFlags |= CONTEXT_XSTATE_FLAG;
> > > + set_xstate_features_mask (context, xstate_features);
> > > + }
> > > + });
> > > }
> > >
> > > static void
> > > @@ -477,26 +495,40 @@ is_segment_register (int r)
> > >
> > > template<typename Context>
> > > static char *
> > > -get_context_reg_ptr (Context *context, int r)
> > > +get_context_reg_ptr (Context *context, int r, const target_desc *tdesc)

Similar feedback for the tdesc parameter for the function comment.

> > > {
> > > const int *mappings;
> > > int mappings_count;
> > > + bool amd64;
> > > #ifdef __x86_64__
> > > if (!windows_process.wow64_process)
> > > {
> > > mappings = amd64_mappings;
> > > mappings_count = sizeof (amd64_mappings) / sizeof
> > > (amd64_mappings[0]);
> > > + amd64 = true;
> > > }
> > > else
> > > #endif
> > > {
> > > mappings = i386_mappings;
> > > mappings_count = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
> > > + amd64 = false;
> > > }
> > >
> > > + int ymm0h_regnum;
> > > + const int num_xmm_registers = amd64 ? 16 : 8;
> > > +
> > > char *context_offset;
> > > if (r < mappings_count)
> > > context_offset = (char *) context + mappings[r];
> > > + else if ((xstate_features & X86_XSTATE_AVX) != 0
> > > + && r >= (ymm0h_regnum = find_regno (tdesc, "ymm0h"))
> > > + && r < ymm0h_regnum + num_xmm_registers)
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_AVX_ID, nullptr);
> >
> > We don't check "context_offset" for nulltpr before adding the offsets. We're
> > checking for nullptr and size explicitly in "zero_xstate_features". So, I was
> > wondering if we should add checks here, too. IIUC, it should not be possible
> > to have "locate_xstate_feature () == nullptr" at this point. Maybe add an
> > assert for consistency?
> 
> Same for x86-windows-nat.c?

If we keep the code as is, it might be a good idea. But this might also change with the
result of our general discussion for the use of locate_xstate_feature.

> > > + context_offset += 16 * (r - ymm0h_regnum);
> > > + }
> > > else
> > > gdb_assert_not_reached ("invalid register number %d", r);
> > >
> > > @@ -510,7 +542,7 @@ i386_fetch_inferior_register (struct regcache
> > > *regcache,
> > > {
> > > char *context_offset = windows_process.with_context (th, [&] (auto
> > > *context)
> > > {
> > > - return get_context_reg_ptr (context, r);
> > > + return get_context_reg_ptr (context, r, regcache->tdesc);
> > > });
> > >
> > > /* GDB treats some registers as 32-bit, where they are in fact only
> > > @@ -538,7 +570,7 @@ i386_store_inferior_register (struct regcache
> > > *regcache,
> > > {
> > > char *context_offset = windows_process.with_context (th, [&] (auto
> > > *context)
> > > {
> > > - return get_context_reg_ptr (context, r);
> > > + return get_context_reg_ptr (context, r, regcache->tdesc);
> > > });
> > >
> > > /* GDB treats some registers as 32-bit, where they are in fact only
> > > @@ -571,14 +603,17 @@ i386_arch_setup (void)
> > > {
> > > target_desc_up tdesc;
> > >
> > > + DWORD64 xcr0 = xstate_features;
> > > + if (xcr0 == 0)
> > > + xcr0 = X86_XSTATE_SSE_MASK;

You could call this xstate_bv instead even though you shadow stacks are not supported yet.
This has changed in commit: " gdb, gdbserver: Use xstate_bv for target description creation on x86."

> > > +
> > > #ifdef __x86_64__
> > > - tdesc = amd64_create_target_description (X86_XSTATE_SSE_MASK, false,
> > > - false, false);
> > > + tdesc = amd64_create_target_description (xcr0, false, false, false);
> > > init_target_desc (tdesc.get (), amd64_expedite_regs, WINDOWS_OSABI);
> > > win32_tdesc = std::move (tdesc);
> > > #endif
> > >
> > > - tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false,
> > > false);
> > > + tdesc = i386_create_target_description (xcr0, false, false);
> > > init_target_desc (tdesc.get (), i386_expedite_regs, WINDOWS_OSABI);
> > > #ifdef __x86_64__
> > > wow64_win32_tdesc = std::move (tdesc);
> > > diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
> > > index 1103a802db7..3e80405f651 100644
> > > --- a/gdbserver/win32-low.cc
> > > +++ b/gdbserver/win32-low.cc
> > > @@ -33,6 +33,7 @@
> > > #include <process.h>
> > > #include "gdbsupport/gdb_tilde_expand.h"
> > > #include "gdbsupport/common-inferior.h"
> > > +#include "tdesc.h"
> > >
> > > using namespace windows_nat;
> > >
> > > @@ -427,8 +428,9 @@ child_fetch_inferior_registers (struct regcache
> > > *regcache, int r)
> > > int regno;
> > > windows_thread_info *th = windows_process.find_thread (current_thread-
> > > >id);
> > > win32_require_context (th);
> > > - if (r == -1 || r > NUM_REGS)
> > > - child_fetch_inferior_registers (regcache, NUM_REGS);
> > With r != -1 and r > regcache->tdesc->reg_defs.size (), this may fall through into
> > "get_context_reg_ptr" and eventually into the gdb_assert_not_reached_part.
> >
> > Maybe add another check, e.g.,
> >
> > int num_regs = regcache->tdesc->reg_defs.size ();
> > if (r == -1 || r > num_regs)
> > r = num_regs;
> >
> > Same for child_store_inferior_registers.
> 
> Adding this is fine with me, but I just wonder why r > reg_defs.size()
> shouldn't get to gdb_assert_not_reached_part.

I am +1 for just having the gdb_assert_not_reached deeper down in the stack - to avoid duplication.
But Stephan might have a different opinion on that.

I'd rather improve the function description for the parameter R, but this should be
be an additional patch (since you don't touch the function description).
And you of course don't have to do this. If you want to do this, it could also be independent of this series.

Similar suggestion for the removal of "r==0" in  child_store_inferior_registers below
(which you had in v3). I think it's a good idea.
But same as above: if you want to do this, it could also be independent of this series and should be a separate patch.

> > > + if (r == -1)
> > > + child_fetch_inferior_registers (regcache,
> > > + regcache->tdesc->reg_defs.size ());
> > > else
> > > for (regno = 0; regno < r; regno++)
> > > (*the_low_target.fetch_inferior_register) (regcache, th, regno);
> > > @@ -442,8 +444,9 @@ child_store_inferior_registers (struct regcache
> > > *regcache, int r)
> > > int regno;
> > > windows_thread_info *th = windows_process.find_thread (current_thread-
> > > >id);
> > > win32_require_context (th);
> > > - if (r == -1 || r == 0 || r > NUM_REGS)
> > > - child_store_inferior_registers (regcache, NUM_REGS);
> > > + if (r == -1 || r == 0)
> > > + child_store_inferior_registers (regcache,
> > > + regcache->tdesc->reg_defs.size ());
> > > else
> > > for (regno = 0; regno < r; regno++)
> > > (*the_low_target.store_inferior_register) (regcache, th, regno);
> > > @@ -1347,7 +1350,9 @@ void
> > > initialize_low (void)
> > > {
> > > set_target_ops (&the_win32_target);
> > > - the_low_target.arch_setup ();
> > >
> > > initialize_loadable ();
> > > + /* Has to be done after initialize_loadable, because it uses the xstate
> > > + functions if available. */
> > > + the_low_target.arch_setup ();
> > > }
> > > --
> > > 2.55.0
> 
> 
> Hannes

Christina
________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* RE: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
  2026-10-09 14:36       ` Hannes Domani
  2026-10-12  7:59         ` Joos, Christina
@ 2026-10-14 13:06         ` Joos, Christina
  1 sibling, 0 replies; 18+ messages in thread
From: Joos, Christina @ 2026-10-14 13:06 UTC (permalink / raw)
  To: Hannes Domani, gdb-patches, Rohr, Stephan

> -----Original Message-----
> From: Hannes Domani <ssbssa@yahoo.de>
> Sent: Freitag, 9. Oktober 2026 16:37
> To: gdb-patches@sourceware.org; Rohr, Stephan <stephan.rohr@intel.com>
> Cc: Joos, Christina <christina.joos@intel.com>
> Subject: Re: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
> 
>  Am Montag, 5. Oktober 2026 um 16:09:19 MESZ hat Rohr, Stephan
> <stephan.rohr@intel.com> Folgendes geschrieben:
> 
> > Hi Hanns,
> >
> > also here, some minor findings below.
> >
> > Thanks
> > Stephan
> >
> > > -----Original Message-----
> > > From: Hannes Domani <ssbssa@yahoo.de>
> > > Sent: Wednesday, 30 September 2026 17:12
> > > To: gdb-patches@sourceware.org
> > > Subject: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register
> > > support
> > >
> > > Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for
> > > Linux,
> >
> > Maybe name the commit title instead of the hash. Not sure what is best
> > practice for this.
> 
> This part was suggested to me in another review, so maybe I should just add
> both commit hash and title.
> 
> 
> > > this patch adds support for the Intel AVX-512 registers for 32 and
> > > 64-bit mode on Windows.
> > > It enables accessing registers $ymm0 - $ymm31, $zmm0 - $zmm31, and
> > > $k0 - $k7 where they are available.
> > >
> >
> > Wouldn't we want to mention "It enables accessing registers
> > $ymm16 - $ymm31 [..]" instead?
> 
> Ok.
> 
> 
> > > After this patch gdb.arch/i386-avx512.exp passes on windows.
> > > ---
> > > v3:
> > > - merged gdb+gdbserver parts, and split again AVX/AVX-512 parts
> > > v4:
> > > - Add reference to equivalent Linux commit in commit message
> > > - Add check for enabled xstate_features in get_context_reg_ptr of
> > > x86-windows-nat.c
> > > - Changed all NULL to nullptr
> > > ---
> > > gdb/NEWS | 4 +++-
> > > gdb/nat/windows-nat.c | 4 ++--
> > > gdb/x86-windows-nat.c | 40 +++++++++++++++++++++++++++++++
> > > gdbserver/win32-i386-low.cc | 48
> > > ++++++++++++++++++++++++++++++++++++-
> > > 4 files changed, 92 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/gdb/NEWS b/gdb/NEWS
> > > index da4bc811c3a..704e6a7c8ba 100644
> > > --- a/gdb/NEWS
> > > +++ b/gdb/NEWS
> > > @@ -195,7 +195,9 @@ info locals
> > > The s390 64-bit target (s390x-*) remains supported.
> > >
> > > * Support for Intel AVX registers on Windows.
> > > - Support displaying and modifying Intel AVX registers $ymm0 - $ymm15.
> > > + Support displaying and modifying Intel AVX registers $ymm0 - $ymm31.
> >
> > AVX is limited to $ymm0 - $ymm15. Maybe add another bullet "Support
> > for Intel AVX-512 registers on Windows." and list what's introduced in
> > this patch.
> 
> Ok.
> 
> 
> > > + Support displaying and modifying Intel AVX-512 registers $zmm0 -
> > > + $zmm31 and $k0 - $k7.
> > >
> > > * Configure changes
> > >
> > > diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c index
> > > cd3c827a5d5..3940465d06b 100644
> > > --- a/gdb/nat/windows-nat.c
> > > +++ b/gdb/nat/windows-nat.c
> > > @@ -290,7 +290,7 @@ windows_thread_info::zero_xstate_features () if
> > > (zeroed_features == 0) return;
> > >
> > > - for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_AVX_ID; f++)
> > > + for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_ZMM_ID; f++)
> > > {
> > > DWORD64 flag = 1ULL << f;
> > > if ((zeroed_features & flag) != 0)
> > > @@ -1373,7 +1373,7 @@ initialize_loadable () {
> > > /* Available XState features masked with implemented features. */
> > > xstate_features = (GetEnabledXStateFeatures ()
> > > - & X86_XSTATE_AVX_MASK);
> > > + & X86_XSTATE_AVX_AVX512_MASK);
> >
> > I think it makes sense to add a check that bits X86_XSTATE_K,
> X86_XSTATE_ZMM_H
> > and X86_XSTATE_ZMM are all set. x86-xstate.h explicitly mentions
> > "AVX 512 adds three feature bits. All three must be enabled.". I know this is a
> > theoretical example but it doesn't hurt, e.g.,
> >
> > if ((xstate_features & X86_XSTATE_AVX512) != X86_XSTATE_AVX512)
> > xstate_features &= ~X86_XSTATE_AVX512;
> 
> I don't really get the why, but ok.
> 
> 
> > > /* The extended XState functions are only needed if the available
> > > features exceed SSE. */
> > > if ((xstate_features & ~X86_XSTATE_SSE_MASK) == 0)
> > > diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c
> > > index 1e44a45171c..afc71b4ef61 100644
> > > --- a/gdb/x86-windows-nat.c
> > > +++ b/gdb/x86-windows-nat.c
> > > @@ -275,6 +275,46 @@ get_context_reg_ptr (Context *context, int r,
> > > i386_gdbarch_tdep *tdep)
> > > (context, X86_XSTATE_AVX_ID, nullptr);
> > > context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep));
> > > }
> > > + else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> > > + && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> > > I387_ZMM0H_REGNUM (tdep)
> > > + && r < I387_ZMM16H_REGNUM (tdep) && r <
> > > I387_ZMMENDH_REGNUM (tdep))
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_H_ID, nullptr);
> > > + context_offset += 32 * (r - I387_ZMM0H_REGNUM (tdep));
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > > + && I387_ZMM0H_REGNUM (tdep) > 0 && r >=
> > > I387_ZMM16H_REGNUM (tdep)
> > > + && r < I387_ZMMENDH_REGNUM (tdep))
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > > + context_offset += 32 + 64 * (r - I387_ZMM16H_REGNUM (tdep));
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_K) != 0
> > > + && I387_K0_REGNUM (tdep) > 0 && r >= I387_K0_REGNUM (tdep)
> > > + && r < I387_KEND_REGNUM (tdep))
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_K_ID, nullptr);
> > > + context_offset += 8 * (r - I387_K0_REGNUM (tdep));
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > > + && I387_YMM16H_REGNUM (tdep) > 0 && r >=
> > > I387_YMM16H_REGNUM (tdep)
> > > + && r < I387_YMMH_AVX512_END_REGNUM (tdep))
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > > + context_offset += 16 + 64 * (r - I387_YMM16H_REGNUM (tdep));
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > > + && I387_XMM16_REGNUM (tdep) > 0 && r >=
> > > I387_XMM16_REGNUM (tdep)
> > > + && r < I387_XMM_AVX512_END_REGNUM (tdep))
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > > + context_offset += 64 * (r - I387_XMM16_REGNUM (tdep));
> > > + }
> > > else
> > > gdb_assert_not_reached ("invalid register number %d", r);
> > >
> > > diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc
> > > index 1a45b15e0cf..8c62787a31b 100644
> > > --- a/gdbserver/win32-i386-low.cc
> > > +++ b/gdbserver/win32-i386-low.cc
> > > @@ -515,8 +515,11 @@ get_context_reg_ptr (Context *context, int r,
> const
> > > target_desc *tdesc)
> > > amd64 = false;
> > > }
> > >
> > > - int ymm0h_regnum;
> > > + int ymm0h_regnum, zmm0h_regnum, k0_regnum;
> > > + int xmm16_regnum, ymm16h_regnum, zmm16h_regnum;
> > > const int num_xmm_registers = amd64 ? 16 : 8;
> > > + const int num_zmm_high_registers = amd64 ? 16 : 0;
> > > + const int num_avx512_k_registers = 8;
> > >
> > > char *context_offset;
> > > if (r < mappings_count)
> > > @@ -529,6 +532,49 @@ get_context_reg_ptr (Context *context, int r,
> const
> > > target_desc *tdesc)
> > > (context, X86_XSTATE_AVX_ID, nullptr);
> > > context_offset += 16 * (r - ymm0h_regnum);
> > > }
> > > + else if ((xstate_features & X86_XSTATE_ZMM_H) != 0
> > > + && r >= (zmm0h_regnum = find_regno (tdesc, "zmm0h"))
> > > + && r < zmm0h_regnum + num_xmm_registers)
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_H_ID, nullptr);
> > > + context_offset += 32 * (r - zmm0h_regnum);
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > > + && num_zmm_high_registers != 0
> > > + && r >= (zmm16h_regnum = find_regno (tdesc, "zmm16h"))
> > > + && r < zmm16h_regnum + num_zmm_high_registers)
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > > + context_offset += 32 + 64 * (r - zmm16h_regnum);
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_K) != 0
> > > + && r >= (k0_regnum = find_regno (tdesc, "k0"))
> > > + && r < k0_regnum + num_avx512_k_registers)
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_K_ID, nullptr);
> > > + context_offset += 8 * (r - k0_regnum);
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > > + && num_zmm_high_registers != 0
> > > + && r >= (ymm16h_regnum = find_regno (tdesc, "ymm16h"))
> > > + && r < ymm16h_regnum + num_zmm_high_registers)
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > > + context_offset += 16 + 64 * (r - ymm16h_regnum);
> > > + }
> > > + else if ((xstate_features & X86_XSTATE_ZMM) != 0
> > > + && num_zmm_high_registers != 0
> > > + && r >= (xmm16_regnum = find_regno (tdesc, "xmm16"))
> > > + && r < xmm16_regnum + num_zmm_high_registers)
> > > + {
> > > + context_offset = (char *) locate_xstate_feature
> > > + (context, X86_XSTATE_ZMM_ID, nullptr);
> > > + context_offset += 64 * (r - xmm16_regnum);
> > > + }
> > > else
> > > gdb_assert_not_reached ("invalid register number %d", r);
> > >
> > > --
> > > 2.55.0

I agree with all the comments Stephan has made here. I don't have any additional remarks,
except for the point about locate_xstate_feature, which is relevant to the AVX patch as well
and handled in a different thread.

Regards,
Christina
________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* RE: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
  2026-10-12 18:33           ` Hannes Domani
@ 2026-10-26 12:28             ` Joos, Christina
  0 siblings, 0 replies; 18+ messages in thread
From: Joos, Christina @ 2026-10-26 12:28 UTC (permalink / raw)
  To: Hannes Domani, gdb-patches, Rohr, Stephan

> -----Original Message-----
> From: Hannes Domani <ssbssa@yahoo.de>
> Sent: Montag, 12. Oktober 2026 20:33
> To: gdb-patches@sourceware.org; Rohr, Stephan <stephan.rohr@intel.com>;
> Joos, Christina <christina.joos@intel.com>
> Subject: Re: [PATCH v4 8/9] Windows gdb: Implement AVX-512 register support
> 
>  Am Montag, 12. Oktober 2026 um 09:59:47 MESZ hat Joos, Christina
> <christina.joos@intel.com> Folgendes geschrieben:
> 
> > Hi Hannes,
> >
> > Thanks for continuing to work on this.
> >
> > > > > Similar to commit 01f9f808e2e86187c95e7cff4aeb014a421a53ce for
> > > > > Linux,
> > > >
> > > > Maybe name the commit title instead of the hash. Not sure what is
> > > > best practice for this.
> > >
> > > This part was suggested to me in another review, so maybe I should
> > > just add both commit hash and title.
> >
> > Showing the commit message is definitely a good idea.
> > My initial review wasn't specific on how exactly you should reference the
> commit, sorry for that.
> > I think this commit is a good example:
> >
> > https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=6b369b641c0e
> > feee51356f72d7b317a8906bb8f3
> >
> > I just started looking at this again and have one question upfront:
> > You explained that you ran the dedicated tests for AVX/AVX-512 etc, but has
> this series also been regression-tested?
> 
> Sadly, the testsuite is very unreliable on windows (even though it improved a
> lot recently).
> 
> I now let it first run with current master as baseline:
> 
> # of expected passes 42520
> # of unexpected failures 3334
> # of unexpected successes 1
> # of expected failures 25
> # of known failures 45
> # of untested testcases 133
> # of unresolved testcases 574
> # of unsupported tests 356
> # of paths in test names 32
> # of duplicate test names 60
> 
> Then one time with my AVX changes:
> 
> # of expected passes 41663
> # of unexpected failures 3686
> # of unexpected successes 1
> # of expected failures 26
> # of known failures 45
> # of untested testcases 135
> # of unresolved testcases 565
> # of unsupported tests 355
> # of paths in test names 31
> # of duplicate test names 54
> 
> And again with my changes, so you see what I mean:
> 
> # of expected passes 44348
> # of unexpected failures 2894
> # of unexpected successes 1
> # of expected failures 23
> # of known failures 45
> # of untested testcases 134
> # of unresolved testcases 306
> # of unsupported tests 359
> # of paths in test names 30
> # of duplicate test names 44
> 
> I think it's funny that even the duplicate test names are different each time.
> This was only for gdb.arch/gdb.base/gdb.cp, most of the others wouldn't work
> anyways.
> 
> I can tell you that I first implemented this AVX stuff almost 2 years ago, and had
> no problems using gdb related to it since then.

The GDB testsuite is known to be somewhat flaky:
https://sourceware.org/gdb/wiki/TestingGDB.
However, for linux the requirement is still to do full regressions testing and evaluate
if it's new fails or just flakiness (https://sourceware.org/gdb/wiki/ContributionChecklist).
The situation on Windows is probably a bit different. 

For now, I ran the gdb.arch tests, which I believe are the most relevant ones for this series,
and I did not see any new regressions after applying your patches. Your series clearly improves the situation.
When I continue with gdb.base, I can see that the tests are extremely slow.
I am still waiting for results and am at the same time wondering whether I am doing something wrong.

In any case, I do not think I am the right person to judge whether the regression testing is
sufficiently complete for merging this series.

Also, apologies for the repeated delays. I am currently in a transition/handover phase
before being away for a while (starting middle next week).

Christina



________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

end of thread, other threads:[~2026-10-26 12:29 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20260930151403.774660-1-ssbssa.ref@yahoo.de>
2026-09-30 15:11 ` [PATCH v4 1/9] gdb/testsuite: Add Windows replacement for aligned_alloc Hannes Domani
2026-09-30 15:11   ` [PATCH v4 2/9] Windows gdb: Use allocated buffer for CONTEXT Hannes Domani
2026-09-30 15:11   ` [PATCH v4 3/9] Windows gdb: Remove mappings member from windows_per_inferior Hannes Domani
2026-09-30 15:11   ` [PATCH v4 4/9] Windows gdb: Refactor getting pointer to register inside context Hannes Domani
2026-09-30 15:11   ` [PATCH v4 5/9] Windows gdb: Prepare XState functions Hannes Domani
2026-09-30 15:11   ` [PATCH v4 6/9] Windows gdb: Get available XState features Hannes Domani
2026-09-30 15:11   ` [PATCH v4 7/9] Windows gdb: Implement AVX register support Hannes Domani
2026-10-05 14:09     ` Rohr, Stephan
2026-10-09 14:30       ` Hannes Domani
2026-10-14 13:04         ` Joos, Christina
2026-09-30 15:11   ` [PATCH v4 8/9] Windows gdb: Implement AVX-512 " Hannes Domani
2026-10-05 14:08     ` Rohr, Stephan
2026-10-09 14:36       ` Hannes Domani
2026-10-12  7:59         ` Joos, Christina
2026-10-12 18:33           ` Hannes Domani
2026-10-26 12:28             ` Joos, Christina
2026-10-14 13:06         ` Joos, Christina
2026-09-30 15:11   ` [PATCH v4 9/9] Windows gdbserver: Remove win32_target_ops "num_regs" method Hannes Domani

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox