* [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* 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 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
* [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* 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 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 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
* 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
* [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